progs/scala/autos.scala
author Christian Urban <urbanc@in.tum.de>
Tue, 21 Mar 2017 11:40:22 +0000
changeset 240 820228ac1d0f
parent 239 e59cec211f4f
child 241 1075bba7b8b1
permissions -rw-r--r--
updated for extended partial derivatives
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
239
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
     1
// DFAs and NFAs based on Scala's partial functions
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
     2
import scala.util.Try
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
     3
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
     4
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
     5
// type abbreviation for partial functions
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
     6
type :=>[A, B] = PartialFunction[A, B]
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
     7
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
     8
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
     9
// some states for test cases 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    10
abstract class State
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    11
case object Q0 extends State
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    12
case object Q1 extends State
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    13
case object Q2 extends State
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    14
case object Q3 extends State
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    15
case object Q4 extends State
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    16
case object Q5 extends State
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    17
case object Q6 extends State
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    18
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    19
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    20
// class for DFAs
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    21
case class DFA[A, C](start: A,                // starting state
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    22
                     delta: (A, C) :=> A,     // transition
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    23
                     fins:  A => Boolean) {   // final states
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    24
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    25
  // given a state and a "string", what is the next 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    26
  // state, if there is any?
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    27
  def deltas(q: A, s: List[C]) : A = s match {
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    28
    case Nil => q
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    29
    case c::cs => deltas(delta(q, c), cs)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    30
  }
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    31
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    32
  // is a "string" accepted by an DFA?
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    33
  def accepts(s: List[C]) : Boolean = 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    34
    Try(fins(deltas(start, s))) getOrElse false
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    35
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    36
}
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    37
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    38
// DFA 1
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    39
val dtrans1 : (State, Char) :=> State = 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    40
  { case (Q0, 'a') => Q0 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    41
    case (Q0, 'b') => Q1 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    42
  }
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    43
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    44
val dfa1 = DFA(Q0, dtrans1, Set[State](Q1))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    45
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    46
dfa1.accepts("aaab".toList)     // true
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    47
dfa1.accepts("aacb".toList)     // false
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    48
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    49
// another DFA test
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    50
abstract class S
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    51
case object S0 extends S
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    52
case object S1 extends S
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    53
case object S2 extends S
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    54
case object Sink extends S
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    55
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    56
// transition function with a sink state
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    57
// S0 --a--> S1 --a--> S2
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    58
val sigma : (S, Char) :=> S = 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    59
  { case (S0, 'a') => S1
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    60
    case (S1, 'a') => S2
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    61
    case _ => Sink
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    62
  }
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    63
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    64
val dfa1a = DFA(S0, sigma, Set[S](S2))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    65
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    66
dfa1a.accepts("aa".toList)               //true
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    67
dfa1a.accepts("".toList)                 //false
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    68
dfa1a.accepts("ab".toList)               //false
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    69
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    70
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    71
// class for NFAs
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    72
case class NFA[A, C](starts: Set[A],            // starting states
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    73
                     delta: Set[(A, C) :=> A],  // transitions
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    74
                     fins:  A => Boolean) {     // final states 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    75
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    76
  // given a state and a character, what is the set of next states?
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    77
  // if there is none => empty set
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    78
  def next(q: A, c: C) : Set[A] = 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    79
    delta.flatMap((d) => Try(d(q, c)).toOption)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    80
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    81
  def nexts(qs: Set[A], c: C) : Set[A] =
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    82
    qs.flatMap(next(_, c))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    83
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    84
  // given some states and a string, what is the set of next states?
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    85
  def deltas(qs: Set[A], s: List[C]) : Set[A] = s match {
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    86
    case Nil => qs
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    87
    case c::cs => deltas(nexts(qs, c), cs)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    88
  }
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    89
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    90
  // is a string accepted by an NFA?
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    91
  def accepts(s: List[C]) : Boolean = 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    92
    deltas(starts, s).exists(fins)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    93
}
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    94
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    95
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    96
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    97
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    98
// NFA test cases
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
    99
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   100
// 1 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   101
val trans1 = Set[(State, Char) :=> State](
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   102
  { case (Q0, 'a') => Q1 },
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   103
  { case (Q0, _)   => Q0 },
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   104
  { case (Q1, _)   => Q2 },
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   105
  { case (Q2, _)   => Q3 },
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   106
  { case (Q3, _)   => Q4 },
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   107
  { case (Q4, 'b') => Q5 },
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   108
  { case (Q5, 'c') => Q6 }
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   109
)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   110
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   111
val nfa1 = NFA(Set[State](Q0), trans1, Set[State](Q6))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   112
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   113
nfa1.accepts("axaybzbc".toList)     // true
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   114
nfa1.accepts("aaaaxaybzbc".toList)  // true
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   115
nfa1.accepts("axaybzbd".toList)     // false
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   116
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   117
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   118
// 2
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   119
val trans2 = Set[(State, Char) :=> State](
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   120
  { case (Q0, 'a') => Q0 },
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   121
  { case (Q0, 'a') => Q1 },
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   122
  { case (Q0, 'b') => Q2 },
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   123
  { case (Q1, 'a') => Q1 },
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   124
  { case (Q2, 'b') => Q2 }
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   125
)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   126
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   127
val nfa2 = NFA(Set[State](Q0), trans2, Set[State](Q2))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   128
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   129
nfa2.accepts("aa".toList)             // false
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   130
nfa2.accepts("aaaaa".toList)          // false
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   131
nfa2.accepts("aaaaab".toList)         // true
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   132
nfa2.accepts("aaaaabbb".toList)       // true
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   133
nfa2.accepts("aaaaabbbaaa".toList)    // false
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   134
nfa2.accepts("ac".toList)             // false
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   135
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   136
// 3
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   137
val trans3 = Set[(State, Char) :=> State](
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   138
  { case (Q0, _)   => Q0 },
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   139
  { case (Q0, 'a') => Q1 },
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   140
  { case (Q0, 'b') => Q3 },
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   141
  { case (Q1, 'b') => Q2 },
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   142
  { case (Q2, 'c') => Q5 },
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   143
  { case (Q3, 'c') => Q4 },
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   144
  { case (Q4, 'd') => Q5 }
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   145
)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   146
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   147
val nfa3 = NFA(Set[State](Q0), trans3, Set[State](Q5))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   148
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   149
nfa3.accepts("aaaaabc".toList)      // true
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   150
nfa3.accepts("aaaabcd".toList)      // true
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   151
nfa3.accepts("aaaaab".toList)       // false
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   152
nfa3.accepts("aaaabc".toList)       // true
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   153
nfa3.accepts("aaaaabbbaaa".toList)  // false
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   154
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   155
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   156
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   157
// subset, or powerset, construction
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   158
def powerset[A, C](nfa: NFA[A, C]) : DFA[Set[A], C] = {
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   159
  DFA(nfa.starts, 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   160
      { case (qs, c) => nfa.nexts(qs, c) },
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   161
      _.exists(nfa.fins))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   162
}
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   163
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   164
val dfa2 = powerset(nfa1)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   165
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   166
dfa2.accepts("axaybzbc".toList)     // true
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   167
dfa2.accepts("aaaaxaybzbc".toList)  // true
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   168
dfa2.accepts("axaybzbd".toList)     // false
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   169
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   170
val dfa3 = powerset(nfa2)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   171
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   172
dfa3.accepts("aa".toList)             // false
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   173
dfa3.accepts("aaaaa".toList)          // false
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   174
dfa3.accepts("aaaaab".toList)         // true
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   175
dfa3.accepts("aaaaabbb".toList)       // true
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   176
dfa3.accepts("aaaaabbbaaa".toList)    // false
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   177
dfa3.accepts("ac".toList)             // false
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   178
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   179
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   180
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   181
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   182
// epsilon NFA
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   183
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   184
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   185
// fixpoint construction
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   186
import scala.annotation.tailrec
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   187
@tailrec
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   188
def fixpT[A](f: A => A, x: A): A = {
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   189
  val fx = f(x)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   190
  if (fx == x) x else fixpT(f, fx) 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   191
}
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   192
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   193
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   194
case class eNFA[A, C](starts: Set[A],                    // starting state
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   195
                      delta: Set[(A, Option[C]) :=> A],  // transition edges
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   196
                      fins:  A => Boolean) {             // final states 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   197
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   198
  // epsilon transitions
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   199
  def enext(q: A) : Set[A] = 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   200
    delta.flatMap((d) => Try(d(q, None)).toOption)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   201
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   202
  def enexts(qs: Set[A]) : Set[A] = 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   203
    qs ++ qs.flatMap(enext(_))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   204
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   205
  // epsilon closure
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   206
  def ecl(qs: Set[A]) : Set[A] = 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   207
    fixpT(enexts, qs)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   208
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   209
  // "normal" transition
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   210
  def next(q: A, c: C) : Set[A] = 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   211
    delta.flatMap((d) => Try(d(q, Some(c))).toOption)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   212
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   213
  def nexts(qs: Set[A], c: C) : Set[A] = 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   214
    qs.flatMap(next(_, c))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   215
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   216
  def deltas(qs: Set[A], s: List[C]) : Set[A] = s match {
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   217
    case Nil => ecl(qs)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   218
    case c::cs => deltas(ecl(nexts(ecl(qs), c)), cs)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   219
  }
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   220
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   221
  def accepts(s: List[C]) : Boolean = 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   222
    deltas(starts, s.toList).exists(fins)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   223
}
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   224
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   225
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   226
val etrans1 = Set[(State, Option[Char]) :=> State](
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   227
  { case (Q0, Some('a')) => Q1 },
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   228
  { case (Q1, None) => Q0 }
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   229
)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   230
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   231
val enfa = eNFA(Set[State](Q0), etrans1, Set[State](Q1))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   232
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   233
enfa.accepts("a".toList)              // true
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   234
enfa.accepts("".toList)               // false
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   235
enfa.accepts("aaaaa".toList)          // true
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   236
enfa.accepts("aaaaab".toList)         // flase
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   237
enfa.accepts("aaaaabbb".toList)       // false
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   238
enfa.accepts("aaaaabbbaaa".toList)    // false
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   239
enfa.accepts("ac".toList)             // false
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   240
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   241
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   242
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   243
// Regular expressions fro derivative automata
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   244
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   245
abstract class Rexp
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   246
case object ZERO extends Rexp
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   247
case object ONE extends Rexp
240
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   248
case class CHAR(c: Char) extends Rexp 
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   249
case object ALL extends Rexp 
239
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   250
case class ALT(r1: Rexp, r2: Rexp) extends Rexp 
240
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   251
case class SEQ(r1: Rexp, r2: Rexp) extends Rexp 
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   252
case class STAR(r: Rexp) extends Rexp 
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   253
case class NTIMES(r: Rexp, n: Int) extends Rexp 
239
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   254
case class UPNTIMES(r: Rexp, n: Int) extends Rexp 
240
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   255
case class NOT(r: Rexp) extends Rexp
239
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   256
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   257
def get_chars(r: Rexp) : Set[Char] = r match {
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   258
  case ZERO => Set()
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   259
  case ONE => Set()
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   260
  case CHAR(c) => Set(c)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   261
  case ALT(r1, r2) => get_chars(r1) ++ get_chars(r2)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   262
  case SEQ(r1, r2) => get_chars(r1) ++ get_chars(r2)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   263
  case STAR(r) => get_chars(r)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   264
  case NTIMES(r, _) => get_chars(r)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   265
  case UPNTIMES(r, _) => get_chars(r)
240
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   266
  case ALL => ('a' to 'z').toSet ++ Set('*','/','\\')
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   267
  case NOT(r) => get_chars(r)
239
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   268
}
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   269
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   270
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   271
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   272
import scala.language.implicitConversions    
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   273
import scala.language.reflectiveCalls 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   274
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   275
def charlist2rexp(s: List[Char]): Rexp = s match {
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   276
  case Nil => ONE
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   277
  case c::Nil => CHAR(c)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   278
  case c::s => SEQ(CHAR(c), charlist2rexp(s))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   279
}
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   280
implicit def string2rexp(s: String): Rexp = charlist2rexp(s.toList)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   281
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   282
implicit def RexpOps (r: Rexp) = new {
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   283
  def | (s: Rexp) = ALT(r, s)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   284
  def % = STAR(r)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   285
  def ~ (s: Rexp) = SEQ(r, s)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   286
}
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   287
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   288
implicit def stringOps (s: String) = new {
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   289
  def | (r: Rexp) = ALT(s, r)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   290
  def | (r: String) = ALT(s, r)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   291
  def % = STAR(s)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   292
  def ~ (r: Rexp) = SEQ(s, r)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   293
  def ~ (r: String) = SEQ(s, r)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   294
}
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   295
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   296
def simp(r: Rexp) : Rexp = r match {
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   297
  case ALT(r1, r2) => (simp(r1), simp(r2)) match {
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   298
    case (ZERO, r2s) => r2s
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   299
    case (r1s, ZERO) => r1s
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   300
    case (r1s, r2s) => if (r1s == r2s) r1s else ALT (r1s, r2s)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   301
  }
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   302
  case SEQ(r1, r2) =>  (simp(r1), simp(r2)) match {
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   303
    case (ZERO, _) => ZERO
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   304
    case (_, ZERO) => ZERO
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   305
    case (ONE, r2s) => r2s
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   306
    case (r1s, ONE) => r1s
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   307
    case (r1s, r2s) => SEQ(r1s, r2s)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   308
  }
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   309
  case NTIMES(r, n) => if (n == 0) ONE else NTIMES(simp(r), n)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   310
  case UPNTIMES(r, n) => if (n == 0) ONE else UPNTIMES(simp(r), n)
240
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   311
  case NOT(r) => NOT(simp(r))
239
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   312
  case r => r
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   313
}
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   314
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   315
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   316
// nullable function: tests whether the regular 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   317
// expression can recognise the empty string
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   318
def nullable(r: Rexp) : Boolean = r match {
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   319
  case ZERO => false
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   320
  case ONE => true
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   321
  case CHAR(_) => false
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   322
  case ALL => false
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   323
  case ALT(r1, r2) => nullable(r1) || nullable(r2)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   324
  case SEQ(r1, r2) => nullable(r1) && nullable(r2)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   325
  case STAR(_) => true
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   326
  case NTIMES(r, i) => if (i == 0) true else nullable(r)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   327
  case UPNTIMES(r: Rexp, n: Int) => true
240
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   328
  case NOT(r) => !nullable(r)
239
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   329
}
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   330
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   331
// derivative of a regular expression w.r.t. a character
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   332
def der(c: Char, r: Rexp) : Rexp = r match {
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   333
  case ZERO => ZERO
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   334
  case ONE => ZERO
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   335
  case CHAR(d) => if (c == d) ONE else ZERO
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   336
  case ALL => ONE
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   337
  case ALT(r1, r2) => ALT(der(c, r1), der(c, r2))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   338
  case SEQ(r1, r2) => 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   339
    if (nullable(r1)) ALT(SEQ(der(c, r1), r2), der(c, r2))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   340
    else SEQ(der(c, r1), r2)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   341
  case STAR(r1) => SEQ(der(c, r1), STAR(r1))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   342
  case NTIMES(r1, i) => 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   343
    if (i == 0) ZERO else
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   344
    if (nullable(r1)) SEQ(der(c, r1), UPNTIMES(r1, i - 1))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   345
    else SEQ(der(c, r1), NTIMES(r1, i - 1))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   346
  case UPNTIMES(r1, i) => 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   347
    if (i == 0) ZERO
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   348
    else SEQ(der(c, r1), UPNTIMES(r1, i - 1)) 
240
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   349
  case NOT(r) => NOT(der(c, r))
239
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   350
}
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   351
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   352
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   353
// partial derivative of a regular expression w.r.t. a character
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   354
def pder(c: Char, r: Rexp) : Set[Rexp] = r match {
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   355
  case ZERO => Set()
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   356
  case ONE => Set()
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   357
  case CHAR(d) => if (c == d) Set(ONE) else Set()
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   358
  case ALL => Set(ONE)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   359
  case ALT(r1, r2) => pder(c, r1) ++ pder(c, r2)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   360
  case SEQ(r1, r2) => 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   361
    (for (pr1 <- pder(c, r1)) yield SEQ(pr1, r2)) ++ 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   362
    (if (nullable(r1)) pder(c, r2) else Set())
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   363
  case STAR(r1) => 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   364
    for (pr1 <- pder(c, r1)) yield SEQ(pr1, STAR(r1))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   365
  case NTIMES(r1, i) => 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   366
    if (i == 0) Set() else
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   367
    if (nullable(r1)) 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   368
      for (pr1 <- pder(c, r1)) yield SEQ(pr1, UPNTIMES(r1, i - 1))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   369
    else 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   370
      for (pr1 <- pder(c, r1)) yield SEQ(pr1, NTIMES(r1, i - 1))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   371
  case UPNTIMES(r1, i) => 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   372
    if (i == 0) Set()
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   373
    else 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   374
      for (pr1 <- pder(c, r1)) yield SEQ(pr1, UPNTIMES(r1, i - 1))
240
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   375
  case NOT(r1) => 
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   376
    for (pr1 <- pder(c, r1)) yield NOT(pr1)
239
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   377
}
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   378
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   379
def ppder(c: Char, rs: Set[Rexp]) : Set[Rexp] =
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   380
  rs.flatMap(pder(c, _))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   381
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   382
240
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   383
// matchers
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   384
def matcher(r: Rexp, s: List[Char]): Boolean = s match {
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   385
  case Nil => nullable(r)
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   386
  case c::cs => matcher(der(c, r), cs)
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   387
} 
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   388
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   389
def pmatcher(rs: Set[Rexp], s: List[Char]): Boolean = s match {
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   390
  case Nil => rs.exists(nullable(_))
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   391
  case c::cs => pmatcher(rs.flatMap(pder(c, _)), cs)
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   392
} 
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   393
239
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   394
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   395
// quick-and-dirty translation of a pder automaton 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   396
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   397
val r = STAR(ALL) ~ "a" ~ NTIMES(ALL, 3) ~ "bc"
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   398
val pder_nfa = NFA[Set[Rexp], Char](Set(Set(r)), 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   399
                                    Set( { case (rs, c) => rs.flatMap(pder(c, _))} ), 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   400
                                    _.exists(nullable))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   401
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   402
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   403
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   404
pder_nfa.accepts("axaybzbc".toList)     // true
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   405
pder_nfa.accepts("aaaaxaybzbc".toList)  // true
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   406
pder_nfa.accepts("axaybzbd".toList)     // false
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   407
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   408
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   409
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   410
// Derivative and Partial Derivative Automaton construction
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   411
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   412
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   413
type DState = Rexp                          // state type of the derivative automaton
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   414
type DStates = Set[Rexp]                    
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   415
type Trans = (DState, Char) :=> DState      // transition functions of the der/pder auto
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   416
type MTrans = Map[(DState, Char), DState]   // transition Maps
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   417
type STrans = Set[MTrans]                   // set of transition Maps
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   418
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   419
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   420
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   421
// Brzozoswki Derivative automaton construction ... simple
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   422
// version, might not terminate
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   423
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   424
def goto(sigma: Set[Char], delta: MTrans, qs: DStates, q: DState, c: Char) : (DStates, MTrans) = {
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   425
  val qder = simp(der(c, q))  
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   426
  qs.find(_ == qder) match {
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   427
    case Some(qexists) => (qs, delta + ((q, c) -> qexists))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   428
    case None => explore(sigma, delta + ((q, c) -> qder), qs + qder, qder)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   429
  }
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   430
}
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   431
 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   432
def explore(sigma: Set[Char], delta: MTrans, qs: DStates, q: DState) : (DStates, MTrans) = 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   433
  sigma.foldLeft((qs, delta)) { case ((qs, delta), c) => goto(sigma, delta, qs, q, c) }
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   434
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   435
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   436
def mkDFA(r: Rexp) = {
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   437
  val sigma = get_chars(r)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   438
  val (qs, delta) = explore(sigma, Map(), Set[Rexp](r), r)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   439
  val fins = qs.filter(nullable(_))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   440
  val deltaf : (Rexp, Char) :=> Rexp =  { case (q, c) => delta(q, c) }
240
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   441
  println(s"DFA size: ${qs.size}")
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   442
  println(s"""DFA states\n${qs.mkString("\n")}""")
239
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   443
  DFA(r, deltaf, fins)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   444
}
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   445
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   446
val re = "ab" | "ac"
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   447
val d1 = mkDFA(re)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   448
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   449
d1.accepts("ab".toList) // true
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   450
d1.accepts("ac".toList) // true
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   451
d1.accepts("aa".toList) // false
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   452
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   453
val d2 = mkDFA(r)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   454
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   455
d2.accepts("axaybzbc".toList)     // true
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   456
d2.accepts("aaaaxaybzbc".toList)  // true
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   457
d2.accepts("axaybzbd".toList)     // false
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   458
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   459
for (n <- (1 to 10).toList) 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   460
  mkDFA(STAR(ALL) ~ "a" ~ NTIMES(ALL, n) ~ "bc")
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   461
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   462
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   463
// this is an example where mkDFA does not terminate
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   464
val big_aux = STAR("a" | "b")
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   465
val big = SEQ(big_aux, SEQ("a",SEQ("b", big_aux)))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   466
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   467
//mkDFA(big)   // does not terminate
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   468
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   469
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   470
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   471
// Antimirov Partial derivative automata construction ... definitely terminates
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   472
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   473
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   474
// to transform (concrete) Maps into functions
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   475
def toFun(m: MTrans) : Trans = 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   476
  { case (q, c) => m(q, c) }
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   477
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   478
def pgoto(sigma: Set[Char], delta: STrans, qs: DStates, q: DState, c: Char) : (DStates, STrans) = {
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   479
  val qders = pder(c, q).map(simp(_))  // set of simplified partial derivatives
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   480
  qders.foldLeft((qs, delta)) { case ((qs, delta), qnew) => padd(sigma, delta, qs, q, qnew, c) }
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   481
}
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   482
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   483
def padd(sigma: Set[Char], delta: STrans, qs: DStates, 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   484
         q: DState, qnew: DState, c: Char) : (DStates, STrans) = {
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   485
  qs.find(_ == qnew) match {
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   486
    case Some(qexists) => (qs, delta + Map((q, c) -> qexists))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   487
    case None => pexplore(sigma, delta + Map((q, c) -> qnew), qs + qnew, qnew)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   488
  }
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   489
}
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   490
 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   491
def pexplore(sigma: Set[Char], delta: STrans, qs: DStates, q: DState) : (DStates, STrans) = 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   492
  sigma.foldLeft((qs, delta)) { case ((qs, delta), c) => pgoto(sigma, delta, qs, q, c) }
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   493
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   494
def mkNFA(r: Rexp) : NFA[Rexp, Char]= {
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   495
  val sigma = get_chars(r)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   496
  val (qs, delta) = pexplore(sigma, Set(), Set(r), r)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   497
  val fins = qs.filter(nullable(_))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   498
  val deltaf = delta.map(toFun(_))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   499
  println(s"NFA size: ${qs.size}")
240
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   500
  println(s"""NFA states\n${qs.mkString("\n")}""")
239
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   501
  NFA(Set(r), deltaf, fins)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   502
}
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   503
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   504
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   505
// simple example from Scott's paper
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   506
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   507
val n1 = mkNFA(re) // size = 4
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   508
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   509
n1.accepts("ab".toList) // true
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   510
n1.accepts("ac".toList) // true
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   511
n1.accepts("aa".toList) // false
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   512
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   513
// example from: Partial Derivative and Position Bisimilarity 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   514
// Automata, Eva Maia, Nelma Moreira, Rogerio Reis
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   515
 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   516
val r_test = STAR(("a" ~ STAR("b")) | "b") ~ "a"
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   517
val t1 = pder('a', r_test).map(simp(_))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   518
val t2 = pder('b', r_test).map(simp(_))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   519
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   520
mkNFA(r_test) // size = 3
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   521
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   522
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   523
// simple example involving double star 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   524
// with depth-first search causes catastrophic backtracing
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   525
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   526
val n2 = mkNFA(STAR(STAR("a")) ~ "b")  // size 3
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   527
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   528
n2.accepts("aaaaaab".toList)   // true
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   529
n2.accepts("aaaaaa".toList)    // false
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   530
n2.accepts(("a" * 100).toList) // false
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   531
240
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   532
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   533
// example involving not
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   534
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   535
val rnot = "/*" ~ (NOT ((ALL.%) ~ "*/" ~ (ALL.%))) ~ "*/"
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   536
val nnot = mkNFA(rnot)  // size 7
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   537
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   538
nnot.accepts("/**/".toList)        // true
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   539
nnot.accepts("/*aaabaa*/".toList)  // true
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   540
nnot.accepts("/*/**/".toList)      // true
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   541
nnot.accepts("/*aaa*/aa*/".toList) // false  ????
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   542
nnot.accepts("/aaa*/aa*/".toList) // false
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   543
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   544
matcher(rnot, "/**/".toList)        // true
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   545
matcher(rnot, "/*aaabaa*/".toList)  // true
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   546
matcher(rnot, "/*/**/".toList)      // true
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   547
matcher(rnot, "/*aaa*/aa*/".toList) // false
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   548
matcher(rnot, "/aaa*/aa*/".toList) // false
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   549
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   550
pmatcher(Set(rnot), "/**/".toList)        // true
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   551
pmatcher(Set(rnot), "/*aaabaa*/".toList)  // true
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   552
pmatcher(Set(rnot), "/*/**/".toList)      // true
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   553
pmatcher(Set(rnot), "/*aaa*/aa*/".toList) // false  ?????
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   554
pmatcher(Set(rnot), "/aaa*/aa*/".toList) // false
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   555
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   556
// example from automata paper with counters and backreferences
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   557
239
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   558
val r1 = STAR(ALL) ~ "a" ~ NTIMES(ALL, 1) ~ "bc"
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   559
mkNFA(r1)     // size = 5
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   560
 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   561
val n3 = mkNFA(r) // size = 7
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   562
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   563
n3.accepts("axaybzbc".toList)     // true
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   564
n3.accepts("aaaaxaybzbc".toList)  // true
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   565
n3.accepts("axaybzbd".toList)     // false
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   566
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   567
for (n <- (1 to 100).toList) 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   568
  mkNFA(STAR(ALL) ~ "a" ~ NTIMES(ALL, n) ~ "bc")