progs/scala/autos.scala
author Christian Urban <urbanc@in.tum.de>
Wed, 29 Mar 2017 05:50:38 +0800
changeset 241 1075bba7b8b1
parent 240 820228ac1d0f
child 242 dcfc9b23b263
permissions -rw-r--r--
updated
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
241
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   256
case class AND(r1: Rexp, r2: Rexp) extends Rexp 
239
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   257
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   258
def get_chars(r: Rexp) : Set[Char] = r match {
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   259
  case ZERO => Set()
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   260
  case ONE => Set()
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   261
  case CHAR(c) => Set(c)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   262
  case ALT(r1, r2) => get_chars(r1) ++ get_chars(r2)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   263
  case SEQ(r1, r2) => get_chars(r1) ++ get_chars(r2)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   264
  case STAR(r) => get_chars(r)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   265
  case NTIMES(r, _) => get_chars(r)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   266
  case UPNTIMES(r, _) => get_chars(r)
240
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   267
  case ALL => ('a' to 'z').toSet ++ Set('*','/','\\')
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   268
  case NOT(r) => get_chars(r)
241
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   269
  case AND(r1, r2) => get_chars(r1) ++ get_chars(r2)
239
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
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   273
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   274
import scala.language.implicitConversions    
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   275
import scala.language.reflectiveCalls 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   276
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   277
def charlist2rexp(s: List[Char]): Rexp = s match {
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   278
  case Nil => ONE
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   279
  case c::Nil => CHAR(c)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   280
  case c::s => SEQ(CHAR(c), charlist2rexp(s))
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 string2rexp(s: String): Rexp = charlist2rexp(s.toList)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   283
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   284
implicit def RexpOps (r: Rexp) = new {
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   285
  def | (s: Rexp) = ALT(r, s)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   286
  def % = STAR(r)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   287
  def ~ (s: Rexp) = SEQ(r, s)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   288
}
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   289
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   290
implicit def stringOps (s: String) = new {
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   291
  def | (r: Rexp) = ALT(s, r)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   292
  def | (r: String) = ALT(s, r)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   293
  def % = STAR(s)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   294
  def ~ (r: Rexp) = SEQ(s, r)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   295
  def ~ (r: String) = SEQ(s, r)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   296
}
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   297
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   298
def simp(r: Rexp) : Rexp = r match {
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   299
  case ALT(r1, r2) => (simp(r1), simp(r2)) match {
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   300
    case (ZERO, r2s) => r2s
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   301
    case (r1s, ZERO) => r1s
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   302
    case (r1s, r2s) => if (r1s == r2s) r1s else ALT (r1s, r2s)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   303
  }
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   304
  case SEQ(r1, r2) =>  (simp(r1), simp(r2)) match {
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   305
    case (ZERO, _) => ZERO
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   306
    case (_, ZERO) => ZERO
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   307
    case (ONE, r2s) => r2s
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   308
    case (r1s, ONE) => r1s
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   309
    case (r1s, r2s) => SEQ(r1s, r2s)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   310
  }
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   311
  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
   312
  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
   313
  case NOT(r) => NOT(simp(r))
241
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   314
  case AND(r1, r2) => AND(simp(r1), simp(r2))  
239
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   315
  case r => r
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   316
}
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   317
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   318
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   319
// nullable function: tests whether the regular 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   320
// expression can recognise the empty string
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   321
def nullable(r: Rexp) : Boolean = r match {
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   322
  case ZERO => false
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   323
  case ONE => true
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   324
  case CHAR(_) => false
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   325
  case ALL => false
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   326
  case ALT(r1, r2) => nullable(r1) || nullable(r2)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   327
  case SEQ(r1, r2) => nullable(r1) && nullable(r2)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   328
  case STAR(_) => true
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   329
  case NTIMES(r, i) => if (i == 0) true else nullable(r)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   330
  case UPNTIMES(r: Rexp, n: Int) => true
240
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   331
  case NOT(r) => !nullable(r)
241
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   332
  case AND(r1, r2) => nullable(r1) && nullable(r2)
239
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   333
}
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   334
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   335
// derivative of a regular expression w.r.t. a character
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   336
def der(c: Char, r: Rexp) : Rexp = r match {
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   337
  case ZERO => ZERO
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   338
  case ONE => ZERO
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   339
  case CHAR(d) => if (c == d) ONE else ZERO
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   340
  case ALL => ONE
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   341
  case ALT(r1, r2) => ALT(der(c, r1), der(c, r2))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   342
  case SEQ(r1, r2) => 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   343
    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
   344
    else SEQ(der(c, r1), r2)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   345
  case STAR(r1) => SEQ(der(c, r1), STAR(r1))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   346
  case NTIMES(r1, i) => 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   347
    if (i == 0) ZERO else
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   348
    if (nullable(r1)) SEQ(der(c, r1), UPNTIMES(r1, i - 1))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   349
    else SEQ(der(c, r1), NTIMES(r1, i - 1))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   350
  case UPNTIMES(r1, i) => 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   351
    if (i == 0) ZERO
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   352
    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
   353
  case NOT(r) => NOT(der(c, r))
241
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   354
  // AND case?
239
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   355
}
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   356
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   357
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   358
// partial derivative of a regular expression w.r.t. a character
241
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   359
// does not work for NOT and AND ... see below
239
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   360
def pder(c: Char, r: Rexp) : Set[Rexp] = r match {
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   361
  case ZERO => Set()
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   362
  case ONE => Set()
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   363
  case CHAR(d) => if (c == d) Set(ONE) else Set()
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   364
  case ALL => Set(ONE)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   365
  case ALT(r1, r2) => pder(c, r1) ++ pder(c, r2)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   366
  case SEQ(r1, r2) => 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   367
    (for (pr1 <- pder(c, r1)) yield SEQ(pr1, r2)) ++ 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   368
    (if (nullable(r1)) pder(c, r2) else Set())
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   369
  case STAR(r1) => 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   370
    for (pr1 <- pder(c, r1)) yield SEQ(pr1, STAR(r1))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   371
  case NTIMES(r1, i) => 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   372
    if (i == 0) Set() else
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   373
    if (nullable(r1)) 
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))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   375
    else 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   376
      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
   377
  case UPNTIMES(r1, i) => 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   378
    if (i == 0) Set()
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   379
    else 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   380
      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
   381
}
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   382
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   383
def ppder(c: Char, rs: Set[Rexp]) : Set[Rexp] =
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   384
  rs.flatMap(pder(c, _))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   385
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   386
240
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   387
// matchers
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   388
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
   389
  case Nil => nullable(r)
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   390
  case c::cs => matcher(der(c, r), cs)
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   391
} 
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
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
   394
  case Nil => rs.exists(nullable(_))
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   395
  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
   396
} 
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   397
239
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   398
241
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   399
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   400
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   401
def seq_add(rss: Set[Set[Rexp]], r2: Rexp) : Set[Set[Rexp]] =
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   402
  for (rs <- rss) yield (for (r <- rs) yield (SEQ(r, r2) : Rexp))
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   403
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   404
def not_add(rss: Set[Set[Rexp]]) : Set[Set[Set[Rexp]]] =
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   405
  for (rs <- rss) yield (for (r <- rs) yield (Set(NOT(r)) : Set[Rexp]))
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   406
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   407
def and_compose(rss1: Set[Set[Rexp]], rss2: Set[Set[Rexp]]) : Set[Set[Rexp]] =
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   408
  for (rs1 <- rss1; rs2 <- rss2) yield rs1 ++ rs2
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   409
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   410
def pder2(c: Char, r: Rexp) : Set[Set[Rexp]] = r match {
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   411
  case ZERO => Set()
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   412
  case ONE => Set()
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   413
  case CHAR(d) => if (c == d) Set(Set(ONE)) else Set()
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   414
  case ALL => Set(Set(ONE))
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   415
  case ALT(r1, r2) => pder2(c, r1) ++ pder2(c, r2)
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   416
  case SEQ(r1, r2) => {
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   417
    val prs1 = seq_add(pder2(c, r1), r2)
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   418
    if (nullable(r1)) (prs1 ++ pder2(c, r2)) else prs1
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   419
  }
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   420
  case STAR(r1) => 
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   421
    seq_add(pder2(c, r1), STAR(r1))
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   422
  case AND(r1, r2) => and_compose(pder2(c, r1), pder2(c, r2))
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   423
  case NOT(r1) => {
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   424
    val prs1 = not_add(pder2(c, r1))
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   425
    if (prs1.isEmpty) Set() else 
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   426
      prs1.tail.foldRight(prs1.head) { (rs1, rs2) => rs1 ++ rs2 }
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   427
  }
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   428
}
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   429
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   430
def pmatcher2(rss: Set[Set[Rexp]], s: List[Char]): Boolean = s match {
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   431
  case Nil => rss.exists((rs) => rs.exists((r) => nullable(r)))
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   432
  case c::cs => pmatcher2(rss.flatMap(_.flatMap(pder2(c, _))), cs)
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   433
} 
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   434
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   435
239
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   436
// quick-and-dirty translation of a pder automaton 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   437
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   438
val r = STAR(ALL) ~ "a" ~ NTIMES(ALL, 3) ~ "bc"
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   439
val pder_nfa = NFA[Set[Rexp], Char](Set(Set(r)), 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   440
                                    Set( { case (rs, c) => rs.flatMap(pder(c, _))} ), 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   441
                                    _.exists(nullable))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   442
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   443
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
pder_nfa.accepts("axaybzbc".toList)     // true
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   446
pder_nfa.accepts("aaaaxaybzbc".toList)  // true
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   447
pder_nfa.accepts("axaybzbd".toList)     // false
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
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   450
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   451
// Derivative and Partial Derivative Automaton construction
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
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   454
type DState = Rexp                          // state type of the derivative automaton
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   455
type DStates = Set[Rexp]                    
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   456
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
   457
type MTrans = Map[(DState, Char), DState]   // transition Maps
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   458
type STrans = Set[MTrans]                   // set of transition Maps
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   459
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   460
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
// Brzozoswki Derivative automaton construction ... simple
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   463
// version, might not terminate
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   464
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   465
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
   466
  val qder = simp(der(c, q))  
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   467
  qs.find(_ == qder) match {
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   468
    case Some(qexists) => (qs, delta + ((q, c) -> qexists))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   469
    case None => explore(sigma, delta + ((q, c) -> qder), qs + qder, qder)
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
}
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
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
   474
  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
   475
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   476
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   477
def mkDFA(r: Rexp) = {
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   478
  val sigma = get_chars(r)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   479
  val (qs, delta) = explore(sigma, Map(), Set[Rexp](r), r)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   480
  val fins = qs.filter(nullable(_))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   481
  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
   482
  println(s"DFA size: ${qs.size}")
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   483
  println(s"""DFA states\n${qs.mkString("\n")}""")
239
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   484
  DFA(r, deltaf, fins)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   485
}
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   486
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   487
val re = "ab" | "ac"
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   488
val d1 = mkDFA(re)
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
d1.accepts("ab".toList) // true
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   491
d1.accepts("ac".toList) // true
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   492
d1.accepts("aa".toList) // false
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
val d2 = mkDFA(r)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   495
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   496
d2.accepts("axaybzbc".toList)     // true
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   497
d2.accepts("aaaaxaybzbc".toList)  // true
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   498
d2.accepts("axaybzbd".toList)     // false
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   499
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   500
for (n <- (1 to 10).toList) 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   501
  mkDFA(STAR(ALL) ~ "a" ~ NTIMES(ALL, n) ~ "bc")
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
// this is an example where mkDFA does not terminate
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   505
val big_aux = STAR("a" | "b")
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   506
val big = SEQ(big_aux, SEQ("a",SEQ("b", big_aux)))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   507
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   508
//mkDFA(big)   // does not terminate
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   509
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   510
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   511
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   512
// Antimirov Partial derivative automata construction ... definitely terminates
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   513
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   514
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   515
// to transform (concrete) Maps into functions
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   516
def toFun(m: MTrans) : Trans = 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   517
  { case (q, c) => m(q, c) }
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   518
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   519
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
   520
  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
   521
  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
   522
}
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   523
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   524
def padd(sigma: Set[Char], delta: STrans, qs: DStates, 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   525
         q: DState, qnew: DState, c: Char) : (DStates, STrans) = {
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   526
  qs.find(_ == qnew) match {
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   527
    case Some(qexists) => (qs, delta + Map((q, c) -> qexists))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   528
    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
   529
  }
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   530
}
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   531
 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   532
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
   533
  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
   534
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   535
def mkNFA(r: Rexp) : NFA[Rexp, Char]= {
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   536
  val sigma = get_chars(r)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   537
  val (qs, delta) = pexplore(sigma, Set(), Set(r), r)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   538
  val fins = qs.filter(nullable(_))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   539
  val deltaf = delta.map(toFun(_))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   540
  println(s"NFA size: ${qs.size}")
240
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   541
  println(s"""NFA states\n${qs.mkString("\n")}""")
239
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   542
  NFA(Set(r), deltaf, fins)
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   543
}
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   544
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   545
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   546
// simple example from Scott's paper
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   547
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   548
val n1 = mkNFA(re) // size = 4
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   549
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   550
n1.accepts("ab".toList) // true
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   551
n1.accepts("ac".toList) // true
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   552
n1.accepts("aa".toList) // false
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   553
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   554
// example from: Partial Derivative and Position Bisimilarity 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   555
// Automata, Eva Maia, Nelma Moreira, Rogerio Reis
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   556
 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   557
val r_test = STAR(("a" ~ STAR("b")) | "b") ~ "a"
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   558
val t1 = pder('a', r_test).map(simp(_))
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   559
val t2 = pder('b', r_test).map(simp(_))
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
mkNFA(r_test) // size = 3
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
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   564
// simple example involving double star 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   565
// with depth-first search causes catastrophic backtracing
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
val n2 = mkNFA(STAR(STAR("a")) ~ "b")  // size 3
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   568
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   569
n2.accepts("aaaaaab".toList)   // true
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   570
n2.accepts("aaaaaa".toList)    // false
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   571
n2.accepts(("a" * 100).toList) // false
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   572
240
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   573
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   574
// example involving not
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   575
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   576
val rnot = "/*" ~ (NOT ((ALL.%) ~ "*/" ~ (ALL.%))) ~ "*/"
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   577
val nnot = mkNFA(rnot)  // size 7
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   578
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   579
nnot.accepts("/**/".toList)        // true
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   580
nnot.accepts("/*aaabaa*/".toList)  // true
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   581
nnot.accepts("/*/**/".toList)      // true
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   582
nnot.accepts("/*aaa*/aa*/".toList) // false  ????
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   583
nnot.accepts("/aaa*/aa*/".toList) // false
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   584
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   585
matcher(rnot, "/**/".toList)        // true
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   586
matcher(rnot, "/*aaabaa*/".toList)  // true
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   587
matcher(rnot, "/*/**/".toList)      // true
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   588
matcher(rnot, "/*aaa*/aa*/".toList) // false
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   589
matcher(rnot, "/aaa*/aa*/".toList) // false
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   590
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   591
pmatcher(Set(rnot), "/**/".toList)        // true
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   592
pmatcher(Set(rnot), "/*aaabaa*/".toList)  // true
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   593
pmatcher(Set(rnot), "/*/**/".toList)      // true
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   594
pmatcher(Set(rnot), "/*aaa*/aa*/".toList) // false  ?????
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   595
pmatcher(Set(rnot), "/aaa*/aa*/".toList) // false
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   596
241
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   597
pmatcher2(Set(Set(rnot)), "/**/".toList)        // true
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   598
pmatcher2(Set(Set(rnot)), "/*aaabaa*/".toList)  // true
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   599
pmatcher2(Set(Set(rnot)), "/*/**/".toList)      // true
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   600
pmatcher2(Set(Set(rnot)), "/*aaa*/aa*/".toList) // false  ?????
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   601
pmatcher2(Set(Set(rnot)), "/aaa*/aa*/".toList) // false
1075bba7b8b1 updated
Christian Urban <urbanc@in.tum.de>
parents: 240
diff changeset
   602
240
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   603
// example from automata paper with counters and backreferences
820228ac1d0f updated for extended partial derivatives
Christian Urban <urbanc@in.tum.de>
parents: 239
diff changeset
   604
239
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   605
val r1 = STAR(ALL) ~ "a" ~ NTIMES(ALL, 1) ~ "bc"
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   606
mkNFA(r1)     // size = 5
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   607
 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   608
val n3 = mkNFA(r) // size = 7
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   609
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   610
n3.accepts("axaybzbc".toList)     // true
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   611
n3.accepts("aaaaxaybzbc".toList)  // true
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   612
n3.accepts("axaybzbd".toList)     // false
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   613
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   614
for (n <- (1 to 100).toList) 
e59cec211f4f added automata implementation
Christian Urban <urbanc@in.tum.de>
parents:
diff changeset
   615
  mkNFA(STAR(ALL) ~ "a" ~ NTIMES(ALL, n) ~ "bc")