Spiral.scala
changeset 0 902326e1615a
child 1 99f4459d9bb6
equal deleted inserted replaced
-1:000000000000 0:902326e1615a
       
     1 import Element.elem
       
     2 import RexpRelated._
       
     3 import RexpRelated.Rexp._
       
     4 import Partial._
       
     5 import BRexp._
       
     6 import scala.collection.mutable.ListBuffer
       
     7 object Spiral{
       
     8 
       
     9   val space = elem(" ")
       
    10   val corner = elem("+")
       
    11 
       
    12   def spiral(nEdges: Int, direction: Int): Element = {
       
    13     if(nEdges == 1)
       
    14       elem("+")
       
    15     else {
       
    16       val sp = spiral(nEdges - 1, (direction + 3) % 4)
       
    17       def verticalBar = elem('|', 1, sp.height)
       
    18       def horizontalBar = elem('-', sp.width, 1)
       
    19       if(direction == 0)
       
    20         (corner beside horizontalBar) above sp//(sp beside space)
       
    21       else if (direction == 1)
       
    22         sp beside (corner above verticalBar)
       
    23       else if (direction == 2)
       
    24         (space beside sp) above (horizontalBar beside corner)
       
    25       else
       
    26         (verticalBar above corner) beside (space above sp)
       
    27     }
       
    28   }
       
    29   val alphabet = ("""abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.:"=()\;-+*!<>\/%{} """+"\n\t").toSet//Set('a','b','c')
       
    30   def bregx_tree(r: BRexp): Element = regx_tree(berase(r))
       
    31   def regx_tree(r: Rexp): Element = aregx_tree(internalise(r))
       
    32   def aregx_tree(r: ARexp): Element = {
       
    33     r match {
       
    34       case ACHAR(bs, d) => {
       
    35         //val Some(d) = alphabet.find(f)
       
    36         d match {
       
    37           case '\n' => elem("\\n")
       
    38           case '\t' => elem("\\t")
       
    39           case ' ' => elem("space")
       
    40           case d => elem(d.toString)
       
    41         }   
       
    42       }
       
    43       case AONE(bs) => {
       
    44         elem("ONE")
       
    45       }
       
    46       case AZERO => {
       
    47         elem("ZERO")
       
    48       }
       
    49       case ASEQ(bs, r1, r2) => {
       
    50         binary_print("SEQ", r1, r2)
       
    51       }
       
    52       case AALTS(bs, rs) => {
       
    53         //elem("Awaiting completion")
       
    54         list_print("ALT", rs)
       
    55       }
       
    56       case ASTAR(bs, r) => {
       
    57         list_print("STA", List(r))
       
    58       }
       
    59     }
       
    60   }
       
    61   val port = elem(" └-")
       
    62   def list_print(name: String, rs: List[ARexp]): Element = {
       
    63     rs match {
       
    64       case r::Nil => {
       
    65         val pref = aregx_tree(r)
       
    66         val head = elem(name)
       
    67         (head left_align (port up_align pref) ) 
       
    68       }
       
    69       case r2::r1::Nil => {
       
    70         binary_print(name, r2, r1)
       
    71       }
       
    72       case r::rs1 => {
       
    73         val pref = aregx_tree(r)
       
    74         val head = elem(name)
       
    75         if (pref.height > 1){
       
    76           val link = elem('|', 1, pref.height - 1)
       
    77           (head left_align ((port above link) beside pref)) left_align tail_print(rs1)    
       
    78         }
       
    79         else{
       
    80           (head left_align (port beside pref) ) left_align tail_print(rs1)
       
    81         }
       
    82       }
       
    83     }
       
    84   }
       
    85   def tail_print(rs: List[ARexp]): Element = {
       
    86     rs match {
       
    87       case r2::r1::Nil => {
       
    88         val pref = aregx_tree(r2)
       
    89         val suff = aregx_tree(r1)
       
    90         if (pref.height > 1){
       
    91           val link = elem('|', 1, pref.height - 1)
       
    92           ((port above link) beside pref) left_align (port up_align suff)
       
    93         }
       
    94         else{
       
    95           (port beside pref) left_align (port up_align suff)
       
    96         } 
       
    97       }
       
    98       case r2::rs1 => {
       
    99         val pref = aregx_tree(r2)
       
   100         
       
   101         if (pref.height > 1){
       
   102           val link = elem('|', 1, pref.height - 1)
       
   103           ((port above link) beside pref) left_align tail_print(rs1)//(port up_align tail_print(rs1) )
       
   104         }
       
   105         else{
       
   106           (port beside pref) left_align tail_print(rs1)//(port up_align tail_print(rs1))
       
   107         } 
       
   108         //pref left_align tail_print(rs1)
       
   109       }
       
   110     }
       
   111   }
       
   112 
       
   113   def binary_print(name: String, r1: ARexp, r2: ARexp): Element = {
       
   114     val pref = aregx_tree(r1)
       
   115     val suff = aregx_tree(r2)
       
   116     val head = elem(name)
       
   117     if (pref.height > 1){
       
   118       val link = elem('|', 1, pref.height - 1)
       
   119       (head left_align ((port above link) beside pref) ) left_align (port up_align suff)
       
   120     }
       
   121     else{
       
   122       (head left_align (port beside pref) ) left_align (port up_align suff)
       
   123     }
       
   124   }
       
   125   val arr_of_size = ListBuffer.empty[Int]
       
   126   def spill(r: Rexp, or: Rexp): Set[Rexp] = {
       
   127     if(r == or) 
       
   128       Set(r)
       
   129     else{
       
   130       r match {
       
   131           case ALTS(rs) => rs.flatMap(r1 => spill(r1, or)).toSet
       
   132           case SEQ(ALTS(rs), r3) => rs.flatMap(r1 => spill(r1, or).map(a => if(a == ONE) r3 else SEQ(a, r3)) ).toSet
       
   133           case ZERO => Set()
       
   134           case r => Set(r)
       
   135       }
       
   136     }
       
   137   }
       
   138   def pC(r: Rexp): Set[Rexp] = {//PD's companion
       
   139     r match {
       
   140       case SEQ(r1, r2) => pC(r2)
       
   141       case ALTS(rs) => rs.flatMap(a => pC(a) ).toSet
       
   142       case CHAR(c) => Set(r)
       
   143       case r => Set()
       
   144     }
       
   145   }
       
   146 
       
   147   def aspill(ar: ARexp, or: Rexp): Set[Rexp] = spill(erase(ar), or)
       
   148   def illustration(r: Rexp, s: String){
       
   149     var i_like_imperative_style = internalise(r)
       
   150     val all_chars = s.toList
       
   151     for (i <- 0 to s.length - 1){
       
   152       val der_res =  bder(all_chars(i), i_like_imperative_style)
       
   153       val simp_res = bsimp(der_res)
       
   154       println("The original regex, the regex after derivative w.r.t " + all_chars(i) + " and the simplification of the derivative.")
       
   155       println(aregx_tree(i_like_imperative_style) up_align aregx_tree(der_res) up_align aregx_tree(simp_res))
       
   156       //println(asize(i_like_imperative_style), asize(der_res), asize(simp_res))
       
   157       arr_of_size += asize(i_like_imperative_style)
       
   158       //println(asize(simp_res), asize(simp_res) / arr_of_size(0) )
       
   159       i_like_imperative_style = simp_res
       
   160     }
       
   161     arr_of_size += asize(i_like_imperative_style)
       
   162   }
       
   163   val ran = scala.util.Random
       
   164   var alphabet_size = 3
       
   165   def balanced_seq_star_gen(depth: Int, star: Boolean): Rexp = {
       
   166     if(depth == 1){
       
   167       ((ran.nextInt(4) + 97).toChar).toString
       
   168     }
       
   169     else if(star){
       
   170       STAR(balanced_seq_star_gen(depth - 1, false))
       
   171     }
       
   172     else{
       
   173       SEQ(balanced_seq_star_gen(depth - 1, true), balanced_seq_star_gen(depth - 1, true))
       
   174     }
       
   175   }
       
   176   def max(i: Int, j: Int): Int = {
       
   177     if(i > j)
       
   178       i
       
   179     else 
       
   180       j
       
   181   }
       
   182   def random_struct_gen(depth:Int): Rexp = {
       
   183     val dice = ran.nextInt(3)
       
   184     val dice2 = ran.nextInt(3)
       
   185     (dice, depth) match {
       
   186       case (_, 0) => ((ran.nextInt(3) + 97).toChar).toString
       
   187       case (0, i) => STAR(random_struct_gen(max(0, i - 1 - dice2)))
       
   188       case (1, i) => SEQ(random_struct_gen(max(0, i - 1 - dice2)), random_struct_gen(max(0, i - 1 - dice2)))
       
   189       case (2, i) => ALTS( List(random_struct_gen(max(0, i - 1 - dice2)), random_struct_gen(max(0, i - 1 - dice2))) )
       
   190     }
       
   191   }
       
   192   def balanced_struct_gen(depth: Int): Rexp = {
       
   193     val dice = ran.nextInt(3)
       
   194     (dice, depth) match {
       
   195       case (_, 0) => ((ran.nextInt(3) + 97).toChar).toString
       
   196       case (0, i) => STAR(random_struct_gen(depth - 1))
       
   197       case (1, i) => SEQ(random_struct_gen(depth - 1), random_struct_gen(depth - 1))
       
   198       case (2, i) => ALTS( List(random_struct_gen(depth - 1), random_struct_gen(depth - 1) ) )
       
   199     }
       
   200   }
       
   201   def rd_string_gen(alp_size: Int, len: Int): String = {
       
   202     if( len > 0)
       
   203       ((ran.nextInt(alp_size) + 97).toChar).toString + rd_string_gen(alp_size, len - 1)
       
   204     else
       
   205       ((ran.nextInt(alp_size) + 97).toChar).toString
       
   206   }
       
   207   def plot(b: List[Int]){
       
   208     println(b(0),b.max)
       
   209 
       
   210   }
       
   211   def dep_exp(depth: List[Int]){
       
   212     for(i <- depth){
       
   213       arr_of_size.clear()
       
   214       val s = rd_string_gen(alphabet_size, (i-8)*(i-8)+10)
       
   215       val r = random_struct_gen(i)
       
   216       println("depth: "+i)
       
   217       illustration(r, s) //"abcabadaaadcabdbabcdaadbabbcbbdabdabbcbdbabdbcdb") 
       
   218       //println("depth: " + i + " general stats:"+ arr_of_size(0), arr_of_size.max, arr_of_size.max/arr_of_size(0))
       
   219       //println("x y label alignment")
       
   220       /*for(i <- 0 to s.length - 1){
       
   221         if(s(i) == '\n')
       
   222           println(i+" "+arr_of_size(i)+" "+"nl"+" -140")
       
   223         else if(s(i) ==  ' ')
       
   224           println(i+" "+arr_of_size(i)+" "+"sp"+" -140")
       
   225         else
       
   226           println(i+" "+arr_of_size(i)+" "+s(i)+" -140")
       
   227       }*/
       
   228       //println(s.length + " " + arr_of_size(s.length) + " ]" + " -140")
       
   229     }
       
   230   }
       
   231   def case_study(ss: List[String], r: Rexp){
       
   232     for(s <- ss){
       
   233       arr_of_size.clear()
       
   234       illustration(r, s)
       
   235       println("x y label alignment")
       
   236       for(i <- 0 to s.length - 1){
       
   237         if(s(i) == '\n')
       
   238           println(i+" "+arr_of_size(i)+" "+"nl"+" -140")
       
   239         else if(s(i) ==  ' ')
       
   240           println(i+" "+arr_of_size(i)+" "+"sp"+" -140")
       
   241         else
       
   242           println(i+" "+arr_of_size(i)+" "+s(i)+" -140")
       
   243       }
       
   244     }
       
   245   }
       
   246   def star_gen(dp: Int): Rexp = {
       
   247     if(dp > 0)
       
   248       STAR(star_gen(dp - 1))
       
   249     else
       
   250       "a"
       
   251   }
       
   252   def strs_gen(len: Int, num: Int): List[String] = {
       
   253     if(num > 0){
       
   254       rd_string_gen(3, len)::strs_gen(len, num - 1)
       
   255     }
       
   256     else{
       
   257       Nil
       
   258     }
       
   259   }
       
   260   def regx_print(r: Rexp): String = {
       
   261     r match {
       
   262       case ZERO =>
       
   263         "ZERO"
       
   264       case CHAR(c) => {
       
   265          //val Some(c) = alphabet.find(f)
       
   266          "\"" + c.toString + "\""
       
   267       }
       
   268       case ONE => {
       
   269         "ONE"
       
   270       }
       
   271       case ALTS(rs) => {
       
   272         "ALTS(List("+(rs.map(regx_print)).foldLeft("")((a, b) => if(a == "") b else a + "," + b)+"))"
       
   273       }
       
   274       case SEQ(r1, r2) => {
       
   275         "SEQ(" + regx_print(r1) + "," + regx_print(r2) + ")"
       
   276       }
       
   277       case STAR(r) => {
       
   278         "STAR(" + regx_print(r) + ")"
       
   279       }
       
   280     }
       
   281   }
       
   282   val mkst = "abcdefghijklmnopqrstuvwxyz"
       
   283   def weak_sub_check(r: Rexp, s: String, i: Int, f: (List[Rexp], Set[Rexp]) => Boolean){
       
   284     //we first compute pders over the set of all strings on the alphabet
       
   285     val pd = pderas(Set(r), i + 4)
       
   286     //then "b-internalise" the regular expression into a brexp(this is essentially 
       
   287     //attaching a bit Z to every alts to signify that they come from the original regular expression)
       
   288     var old = brternalise(r)
       
   289     //this is for comparison between normal simp and the weakened version of simp
       
   290     //normal simp will be performed on syncold
       
   291     //weakend simp will be performed on old
       
   292     var syncold = brternalise(r)
       
   293     val all_chars = s.toList
       
   294     for (i <- 0 to s.length - 1){
       
   295       val syncder_res = brder(all_chars(i), syncold)
       
   296       val syncsimp_res = strong_br_simp(syncder_res)
       
   297       //see brder for detailed explanation
       
   298       //just changes bit Z to S when deriving an ALTS, 
       
   299       //signifying that the structure has been "touched" and
       
   300       //therefore able to be spilled in the bspill function
       
   301       val der_res =  brder(all_chars(i), old)
       
   302       val simp_res = br_simp(der_res)
       
   303       val anatomy = bspill(simp_res)
       
   304       //track if the number of regular expressions exceeds those in the PD set(remember PD means the pders over A*)
       
   305       if(f(anatomy, pd)  == false){
       
   306         /*println("regular expression")
       
   307         println(regx_tree(r))
       
   308         println("string at " + i)
       
   309         println(s)
       
   310         println("partial derivatives")
       
   311         (pd.foreach(a => println(regx_tree(a))))
       
   312         println("simp result")
       
   313         println(bregx_tree(simp_res))
       
   314         println("bspill result")
       
   315         (anatomy.foreach(a => println(regx_tree(a))))*/
       
   316         println(size(berase(syncsimp_res)))
       
   317         println(size(berase(simp_res)))
       
   318         println(anatomy.map(size).sum)
       
   319         println(pd.map(size).sum)
       
   320       }  
       
   321       old = simp_res
       
   322       syncold = syncsimp_res
       
   323     }
       
   324   }
       
   325   def inclusion_truth(anatomy: List[Rexp], pd: Set[Rexp]): Boolean = {
       
   326     val aset = anatomy.toSet
       
   327     if(aset subsetOf pd){
       
   328       true
       
   329     }
       
   330     else{
       
   331       println("inclusion not true")
       
   332       false
       
   333     }
       
   334   }
       
   335   def size_comp(anatomy: List[Rexp], pd: Set[Rexp]):Boolean = {println("size of PD and bspilled simp regx: ", pd.size, anatomy.size); true}
       
   336   def size_expansion_rate(anatomy: List[Rexp], pd: Set[Rexp]): Boolean = if(anatomy.size > (pd.size)*2 ) {println("size of PD and bspilled simp regx: ", pd.size, anatomy.size); inclusion_truth(anatomy, pd); false }else {true}
       
   337   
       
   338   def check_all(){
       
   339     for(i <- 1 to 1)
       
   340     {
       
   341         val s = "bbb"//rd_string_gen(alphabet_size, 5)//"ac"//rd_string_gen(alphabet_size, 5)
       
   342         val r = STAR(STAR(ALTS(List(SEQ(CHAR('b'),CHAR('b')), ALTS(List(CHAR('a'), CHAR('b')))))))//balanced_struct_gen(4)//SEQ(ALTS(List(STAR("a"),ALTS(List("a","c")))),SEQ(ALTS(List("c","a")),ALTS(List("c","b")))) //random_struct_gen(7)
       
   343         //subset_check(r, s)
       
   344         weak_sub_check(r, s, 5, size_expansion_rate)
       
   345     }
       
   346   }
       
   347   def main(args: Array[String]) {
       
   348     check_all()   
       
   349   } 
       
   350 }
       
   351