progs/dfa.scala
author cu
Thu, 19 Oct 2017 11:04:43 +0100
changeset 524 e264779c3411
parent 487 ffbc65112d48
child 576 414f1daf5728
permissions -rw-r--r--
updated
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
485
21dec9df46ba updated
Christian Urban <urbanc@in.tum.de>
parents: 483
diff changeset
     1
// DFAs in Scala  using partial functions
480
14318f1d3b0f updated
Christian Urban <urbanc@in.tum.de>
parents: 145
diff changeset
     2
import scala.util.Try
479
4fcaa5a2d199 updated
Christian Urban <urbanc@in.tum.de>
parents: 145
diff changeset
     3
480
14318f1d3b0f updated
Christian Urban <urbanc@in.tum.de>
parents: 145
diff changeset
     4
// type abbreviation for partial functions
14318f1d3b0f updated
Christian Urban <urbanc@in.tum.de>
parents: 145
diff changeset
     5
type :=>[A, B] = PartialFunction[A, B]
479
4fcaa5a2d199 updated
Christian Urban <urbanc@in.tum.de>
parents: 145
diff changeset
     6
483
faba5360372c updated
Christian Urban <urbanc@in.tum.de>
parents: 481
diff changeset
     7
case class DFA[A, C](start: A,               // starting state
faba5360372c updated
Christian Urban <urbanc@in.tum.de>
parents: 481
diff changeset
     8
                     delta: (A, C) :=> A,    // transition (partial fun)
faba5360372c updated
Christian Urban <urbanc@in.tum.de>
parents: 481
diff changeset
     9
                     fins:  A => Boolean) {  // final states
479
4fcaa5a2d199 updated
Christian Urban <urbanc@in.tum.de>
parents: 145
diff changeset
    10
480
14318f1d3b0f updated
Christian Urban <urbanc@in.tum.de>
parents: 145
diff changeset
    11
  def deltas(q: A, s: List[C]) : A = s match {
14318f1d3b0f updated
Christian Urban <urbanc@in.tum.de>
parents: 145
diff changeset
    12
    case Nil => q
14318f1d3b0f updated
Christian Urban <urbanc@in.tum.de>
parents: 145
diff changeset
    13
    case c::cs => deltas(delta(q, c), cs)
145
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    14
  }
479
4fcaa5a2d199 updated
Christian Urban <urbanc@in.tum.de>
parents: 145
diff changeset
    15
480
14318f1d3b0f updated
Christian Urban <urbanc@in.tum.de>
parents: 145
diff changeset
    16
  def accepts(s: List[C]) : Boolean = 
14318f1d3b0f updated
Christian Urban <urbanc@in.tum.de>
parents: 145
diff changeset
    17
    Try(fins(deltas(start, s))) getOrElse false
479
4fcaa5a2d199 updated
Christian Urban <urbanc@in.tum.de>
parents: 145
diff changeset
    18
}
4fcaa5a2d199 updated
Christian Urban <urbanc@in.tum.de>
parents: 145
diff changeset
    19
487
ffbc65112d48 updated
Christian Urban <urbanc@in.tum.de>
parents: 485
diff changeset
    20
// the example shown in the handout 
145
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    21
abstract class State
480
14318f1d3b0f updated
Christian Urban <urbanc@in.tum.de>
parents: 145
diff changeset
    22
case object Q0 extends State
14318f1d3b0f updated
Christian Urban <urbanc@in.tum.de>
parents: 145
diff changeset
    23
case object Q1 extends State
14318f1d3b0f updated
Christian Urban <urbanc@in.tum.de>
parents: 145
diff changeset
    24
case object Q2 extends State
14318f1d3b0f updated
Christian Urban <urbanc@in.tum.de>
parents: 145
diff changeset
    25
case object Q3 extends State
14318f1d3b0f updated
Christian Urban <urbanc@in.tum.de>
parents: 145
diff changeset
    26
case object Q4 extends State
145
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    27
480
14318f1d3b0f updated
Christian Urban <urbanc@in.tum.de>
parents: 145
diff changeset
    28
val delta : (State, Char) :=> State = 
14318f1d3b0f updated
Christian Urban <urbanc@in.tum.de>
parents: 145
diff changeset
    29
  { case (Q0, 'a') => Q1
14318f1d3b0f updated
Christian Urban <urbanc@in.tum.de>
parents: 145
diff changeset
    30
    case (Q0, 'b') => Q2
14318f1d3b0f updated
Christian Urban <urbanc@in.tum.de>
parents: 145
diff changeset
    31
    case (Q1, 'a') => Q4
14318f1d3b0f updated
Christian Urban <urbanc@in.tum.de>
parents: 145
diff changeset
    32
    case (Q1, 'b') => Q2
14318f1d3b0f updated
Christian Urban <urbanc@in.tum.de>
parents: 145
diff changeset
    33
    case (Q2, 'a') => Q3
14318f1d3b0f updated
Christian Urban <urbanc@in.tum.de>
parents: 145
diff changeset
    34
    case (Q2, 'b') => Q2
14318f1d3b0f updated
Christian Urban <urbanc@in.tum.de>
parents: 145
diff changeset
    35
    case (Q3, 'a') => Q4
14318f1d3b0f updated
Christian Urban <urbanc@in.tum.de>
parents: 145
diff changeset
    36
    case (Q3, 'b') => Q0
14318f1d3b0f updated
Christian Urban <urbanc@in.tum.de>
parents: 145
diff changeset
    37
    case (Q4, 'a') => Q4
14318f1d3b0f updated
Christian Urban <urbanc@in.tum.de>
parents: 145
diff changeset
    38
    case (Q4, 'b') => Q4 }
145
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    39
480
14318f1d3b0f updated
Christian Urban <urbanc@in.tum.de>
parents: 145
diff changeset
    40
val dfa = DFA(Q0, delta, Set[State](Q4))
145
Christian Urban <christian dot urban at kcl dot ac dot uk>
parents:
diff changeset
    41
480
14318f1d3b0f updated
Christian Urban <urbanc@in.tum.de>
parents: 145
diff changeset
    42
dfa.accepts("bbabaab".toList)   // true
14318f1d3b0f updated
Christian Urban <urbanc@in.tum.de>
parents: 145
diff changeset
    43
dfa.accepts("baba".toList)      // false
487
ffbc65112d48 updated
Christian Urban <urbanc@in.tum.de>
parents: 485
diff changeset
    44
ffbc65112d48 updated
Christian Urban <urbanc@in.tum.de>
parents: 485
diff changeset
    45
ffbc65112d48 updated
Christian Urban <urbanc@in.tum.de>
parents: 485
diff changeset
    46
// another DFA test with a Sink state
ffbc65112d48 updated
Christian Urban <urbanc@in.tum.de>
parents: 485
diff changeset
    47
abstract class S
ffbc65112d48 updated
Christian Urban <urbanc@in.tum.de>
parents: 485
diff changeset
    48
case object S0 extends S
ffbc65112d48 updated
Christian Urban <urbanc@in.tum.de>
parents: 485
diff changeset
    49
case object S1 extends S
ffbc65112d48 updated
Christian Urban <urbanc@in.tum.de>
parents: 485
diff changeset
    50
case object S2 extends S
ffbc65112d48 updated
Christian Urban <urbanc@in.tum.de>
parents: 485
diff changeset
    51
case object Sink extends S
ffbc65112d48 updated
Christian Urban <urbanc@in.tum.de>
parents: 485
diff changeset
    52
ffbc65112d48 updated
Christian Urban <urbanc@in.tum.de>
parents: 485
diff changeset
    53
// transition function with a sink state
ffbc65112d48 updated
Christian Urban <urbanc@in.tum.de>
parents: 485
diff changeset
    54
val sigma : (S, Char) :=> S = 
ffbc65112d48 updated
Christian Urban <urbanc@in.tum.de>
parents: 485
diff changeset
    55
  { case (S0, 'a') => S1
ffbc65112d48 updated
Christian Urban <urbanc@in.tum.de>
parents: 485
diff changeset
    56
    case (S1, 'a') => S2
ffbc65112d48 updated
Christian Urban <urbanc@in.tum.de>
parents: 485
diff changeset
    57
    case _ => Sink
ffbc65112d48 updated
Christian Urban <urbanc@in.tum.de>
parents: 485
diff changeset
    58
  }
ffbc65112d48 updated
Christian Urban <urbanc@in.tum.de>
parents: 485
diff changeset
    59
ffbc65112d48 updated
Christian Urban <urbanc@in.tum.de>
parents: 485
diff changeset
    60
val dfa1a = DFA(S0, sigma, Set[S](S2))
ffbc65112d48 updated
Christian Urban <urbanc@in.tum.de>
parents: 485
diff changeset
    61
ffbc65112d48 updated
Christian Urban <urbanc@in.tum.de>
parents: 485
diff changeset
    62
dfa1a.accepts("aa".toList)        // true
ffbc65112d48 updated
Christian Urban <urbanc@in.tum.de>
parents: 485
diff changeset
    63
dfa1a.accepts("".toList)          // false
ffbc65112d48 updated
Christian Urban <urbanc@in.tum.de>
parents: 485
diff changeset
    64
dfa1a.accepts("ab".toList)        // false
ffbc65112d48 updated
Christian Urban <urbanc@in.tum.de>
parents: 485
diff changeset
    65