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