scala/recs2.scala
changeset 269 fa40fd8abb54
parent 239 ac3309722536
child 270 ccec33db31d4
equal deleted inserted replaced
268:002b07ea0a57 269:fa40fd8abb54
       
     1 package object recs2 {
       
     2 
       
     3 //Recursive Functions
       
     4 
       
     5 abstract class Rec {
       
     6   def eval(ns: List[Int]) : Int
       
     7   def eval(ns: Int*) : Int = eval(ns.toList)
       
     8 
       
     9   //syntactic convenience for composition
       
    10   def o(r: Rec) = Cn(r.arity, this, List(r))
       
    11   def o(r: Rec, f: Rec) = Cn(r.arity, this, List(r, f))
       
    12   def o(r: Rec, f: Rec, g: Rec) = Cn(r.arity, this, List(r, f, g))
       
    13   def o(r: Rec, f: Rec, g: Rec, h: Rec) = Cn(r.arity, this, List(r, f, g, h))
       
    14   def arity : Int
       
    15 }
       
    16 
       
    17 case object Z extends Rec {
       
    18   override def eval(ns: List[Int]) = ns match {
       
    19     case n::Nil => 0
       
    20     case _ => throw new IllegalArgumentException("Z args: " + ns)
       
    21   }
       
    22   override def arity = 1
       
    23 } 
       
    24 
       
    25 case object S extends Rec {
       
    26   override def eval(ns: List[Int]) = ns match {
       
    27     case n::Nil => n + 1
       
    28     case _ => throw new IllegalArgumentException("S args: " + ns)
       
    29   }
       
    30   override def arity = 1 
       
    31 } 
       
    32 
       
    33 case class Id(n: Int, m: Int) extends Rec {
       
    34   require(m < n, println("Id m < n:" + m + " " + n))
       
    35 
       
    36   override def eval(ns: List[Int]) = 
       
    37     if (ns.length == n && m < n) ns(m)
       
    38     else throw new IllegalArgumentException("Id args: " + ns + "," + n + "," + m)
       
    39 
       
    40   override def arity = n
       
    41 }
       
    42 
       
    43 case class Cn(n: Int, f: Rec, gs: List[Rec]) extends Rec {
       
    44   require(f.arity == gs.length, 
       
    45           println("CN " + f + "  " + gs.mkString(",") + "\n" + 
       
    46                   "f.arity gs.length:" + f.arity + " " + gs.length))
       
    47   
       
    48   override def eval(ns: List[Int]) = 
       
    49     if (ns.length == n && gs.forall(_.arity == n) && f.arity == gs.length) f.eval(gs.map(_.eval(ns)))
       
    50     else { 
       
    51       val msg = List("Cn f: " + f, 
       
    52                      "n: " + n,
       
    53                      "f arity: " + f.arity, 
       
    54                      "ns-args: " + ns,
       
    55                      "gs arities: " + gs.map(_.arity).mkString(", "),
       
    56                      "gs: " + gs.mkString(", "),
       
    57                      "ns.length == n " + (ns.length == n).toString,
       
    58                      "gs.forall(_.arity == n) " + (gs.forall(_.arity == n)).toString,
       
    59                      "f.arity == gs.length " + (f.arity == gs.length).toString
       
    60                     )
       
    61       throw new IllegalArgumentException(msg.mkString("\n"))
       
    62     }
       
    63 
       
    64   override def arity = n
       
    65   override def toString = f.toString + gs.map(_.toString).mkString ("(",", ", ")")
       
    66 }
       
    67 
       
    68 // syntactic convenience
       
    69 object Cn {
       
    70   def apply(n: Int, f: Rec, g: Rec) : Rec = new Cn(n, f, List(g))
       
    71 }
       
    72 
       
    73 case class Pr(n: Int, f: Rec, g: Rec) extends Rec {
       
    74   override def eval(ns: List[Int]) = 
       
    75     if (ns.length == n + 1) {
       
    76       if (ns.head == 0) f.eval(ns.tail)
       
    77       else {
       
    78         val r = Pr(n, f, g).eval(ns.head - 1 :: ns.tail)
       
    79         g.eval(ns.head - 1 :: r :: ns.tail)
       
    80       }
       
    81     }
       
    82     else {
       
    83       val msg = List("Pr f: " + f, 
       
    84                      "g: " + g,
       
    85                      "n: " + n,
       
    86                      "f arity: " + f.arity,
       
    87                      "g arity: " + g.arity,
       
    88                      "ns-args: " + ns)
       
    89       throw new IllegalArgumentException(msg.mkString("\n"))
       
    90     }
       
    91 
       
    92   override def arity = n + 1
       
    93   override def toString = "Pr(" + f.toString + ", " + g.toString + ")"
       
    94 }
       
    95 
       
    96 // syntactic convenience
       
    97 object Pr {
       
    98   def apply(r: Rec, f: Rec) : Rec = Pr(r.arity, r, f) 
       
    99 }
       
   100 
       
   101 case class Mn(n: Int, f: Rec) extends Rec {
       
   102   def evaln(ns: List[Int], n: Int) : Int = 
       
   103     if (f.eval(n :: ns) == 0) n else evaln(ns, n + 1)
       
   104 
       
   105   override def eval(ns: List[Int]) = 
       
   106     if (ns.length == n) evaln(ns, 0) 
       
   107     else throw new IllegalArgumentException("Mn: args")
       
   108 
       
   109   override def arity = n
       
   110 }
       
   111 
       
   112 object Mn {
       
   113   def apply(f: Rec) : Rec = Mn(f.arity - 1, f)
       
   114 }
       
   115 
       
   116 
       
   117 
       
   118 
       
   119 // Recursive Function examples
       
   120 def Const(n: Int) : Rec = n match {
       
   121   case 0 => Z
       
   122   case n => S o Const(n - 1)
       
   123 }
       
   124 
       
   125 def Swap(f: Rec) = f o (Id(2, 1), Id(2, 0))
       
   126 val Add = Pr(Id(1, 0), S o Id(3, 1))
       
   127 val Mult = Pr(Z, Add o (Id(3, 1), Id(3, 2)))
       
   128 val Power = Swap(Pr(Const(1), Mult o (Id(3, 1), Id(3, 2))))
       
   129 val Fact = (Pr (Const(1), Mult o (S o Id(3, 0), Id(3, 1)))) o (Id(1, 0), Id(1, 0))
       
   130 val Pred = Pr(Z, Id(3, 0)) o (Id(1, 0), Id(1, 0))
       
   131 val Minus = Swap(Pr(Id(1, 0), Pred o Id(3, 1)))
       
   132 
       
   133 val Sign = Minus o (Const(1), Minus o (Const(1), Id(1, 0)))
       
   134 val Not = Minus o (Const(1), Id(1, 0))
       
   135 val Eq = Minus o (Const(1) o Id(2, 0), Add o (Minus, Swap(Minus))) 
       
   136 val Noteq = Not o Eq 
       
   137 val Conj = Sign o Mult
       
   138 val Disj = Sign o Add 
       
   139 val Imp = Disj o (Not o Id(2, 0), Id(2, 1))
       
   140 val Ifz = Pr(Id(2, 0), Id(4, 3))
       
   141 val If = Ifz o (Not o Id(3, 0), Id(3, 1), Id (3, 2))
       
   142 
       
   143 val Less = Sign o (Swap(Minus))
       
   144 val Le = Disj o (Less, Eq)
       
   145 
       
   146 def Sigma1(f: Rec) = Pr(f o (Z o (Id(1, 0)), Id(1, 0)), 
       
   147                         Add o (Id(3, 1), f o (S o Id(3, 0), Id(3, 2))))
       
   148 def Sigma2(f: Rec) = Pr(f o (Z o (Id(2, 0)), Id(2, 0), Id(2, 1)), 
       
   149                         Add o (Id(4, 1), f o (S o Id(4, 0), Id(4, 2), Id(4, 3))))
       
   150 
       
   151 def Accum1(f: Rec) = Pr(f o (Z o (Id(1, 0)), Id(1, 0)), 
       
   152                         Mult o (Id(3, 1), f o (S o Id(3, 0), Id(3, 2))))
       
   153 def Accum2(f: Rec) = Pr(f o (Z o (Id(2, 0)), Id(2, 0), Id(2, 1)), 
       
   154                         Mult o (Id(4, 1), f o (S o Id(4, 0), Id(4, 2), Id(4, 3))))
       
   155 def Accum3(f: Rec) = Pr(f o (Z o (Id(3, 0)), Id(3, 0), Id(3, 1), Id(3, 2)), 
       
   156                         Mult o (Id(5, 1), f o (S o Id(5, 0), Id(5, 2), Id(5, 3), Id(5, 4))))
       
   157 
       
   158 def All1(f: Rec) = Sign o (Accum1(f))
       
   159 def All2(f: Rec) = Sign o (Accum2(f))
       
   160 def All3(f: Rec) = Sign o (Accum3(f))
       
   161 
       
   162 def All1_less(f: Rec) = {
       
   163   val cond1 = Eq o (Id(3, 0), Id(3, 1))
       
   164   val cond2 = f o (Id(3, 0), Id(3, 2))
       
   165   All2(Disj o (cond1, cond2)) o (Id(2, 0), Id(2, 0), Id(2, 1))
       
   166 }
       
   167 
       
   168 def All2_less(f: Rec) = {
       
   169   val cond1 = Eq o (Id(4, 0), Id(4, 1))
       
   170   val cond2 = f o (Id(4, 0), Id(4, 2), Id(4, 3))
       
   171   All3(Disj o (cond1, cond2)) o (Id(3, 0), Id(3, 0), Id(3, 1), Id(3, 2))
       
   172 }
       
   173 
       
   174 def Ex1(f: Rec) = Sign o (Sigma1(f))
       
   175 def Ex2(f: Rec) = Sign o (Sigma2(f))
       
   176 
       
   177 val Quo = {
       
   178   val lhs = S o (Id(3, 0))
       
   179   val rhs = Mult o (Id(3, 2), S o (Id(3, 1)))
       
   180   val cond = Eq o (lhs, rhs)
       
   181   val if_stmt = If o (cond, S o (Id(3, 1)), Id(3, 1))
       
   182   Pr(Z, if_stmt)
       
   183 }
       
   184 
       
   185 def Iter(f: Rec) = Pr(Id(1, 0), f o (Id(3, 1)))
       
   186 
       
   187 def Max1(f: Rec) = Pr(Z, Ifz o (f o (S o (Id(3, 0)), Id(3, 2)), S o (Id(3, 0)), Id(3, 1)))
       
   188 def Max2(f: Rec) = Pr(Z, Ifz o (f o (S o (Id(4, 0)), Id(4, 2), Id(4, 3)), S o (Id(4, 0)), Id(4, 1)))
       
   189  
       
   190 val Triangle = Quo o (Mult o (Id(1, 0), S), Const(2))
       
   191 
       
   192 val MaxTriangle = {
       
   193   val cond = Not o (Le o (Triangle o (Id(2, 0)), Id(2, 1))) 
       
   194   Max1(cond) o (Id(1, 0), Id(1, 0))
       
   195 }
       
   196 
       
   197 val MaxTriangle2 = {
       
   198   Pred o Mn(Le o (Triangle o (Id(2, 0)), Id(2, 1)))
       
   199 }
       
   200 
       
   201 case object MaxTriangleFast extends Rec {
       
   202   def triangle(n: Int) : Int = (n * (n + 1)) / 2
       
   203 
       
   204   def search(m: Int, n: Int) : Int = {
       
   205     if (triangle(n) > m) n - 1 else search(m, n + 1)
       
   206   }
       
   207 
       
   208   override def eval(ns: List[Int]) = ns match {
       
   209     case n::Nil => search(n, 0)
       
   210     case _ => throw new IllegalArgumentException("MT args: " + ns)
       
   211   }
       
   212 
       
   213   override def arity = 1
       
   214 }
       
   215 
       
   216 case object TriangleFast extends Rec {
       
   217   def triangle(n: Int) : Int = (n * (n + 1)) / 2
       
   218 
       
   219   override def eval(ns: List[Int]) = ns match {
       
   220     case n::Nil => triangle(n)
       
   221     case _ => throw new IllegalArgumentException("Tr args: " + ns)
       
   222   }
       
   223 
       
   224   override def arity = 1
       
   225 }
       
   226 
       
   227 //(0 until 200).map(MaxTriangleFast.eval(_))
       
   228 
       
   229 
       
   230 val Penc = Add o (TriangleFast o (Add o (Id(2, 0), Id(2, 1))), Id(2, 0))
       
   231 val Pdec1 = Minus o (Id(1, 0), Triangle o (MaxTriangle o (Id(1, 0)))) 
       
   232 val Pdec2 = Minus o (MaxTriangle o (Id(1, 0)), Pdec1 o (Id(1, 0))) 
       
   233 
       
   234 def Lenc(fs: List[Rec]) : Rec = fs match {
       
   235   case Nil => Z
       
   236   case f::fs => Penc o (S o (f), Lenc(fs))
       
   237 }
       
   238 
       
   239 val Ldec = Pred o (Pdec1 o (Swap (Iter(Pdec2))))
       
   240 
       
   241 val Within = Less o (Z o (Id(2, 0)), Swap (Iter(Pdec2)))
       
   242 val Enclen = (Max1(Not o (Within o (Id(2, 1), Pred o (Id(2, 0)))))) o (Id(1, 0), Id(1, 0))
       
   243  
       
   244 
       
   245 val Read = Ldec o (Id(1, 0), Const(0))
       
   246 val Write = Penc o (S o (Id(2, 0)), Pdec2 o (Id(2, 1)))
       
   247 
       
   248 val Newleft = {
       
   249   val cond0 = Eq o (Id(3, 2), Const(0))
       
   250   val cond1 = Eq o (Id(3, 2), Const(1))
       
   251   val cond2 = Eq o (Id(3, 2), Const(2))
       
   252   val cond3 = Eq o (Id(3, 2), Const(3))
       
   253   val case3 = Penc o (S o (Read o (Id(3, 1))), Id(3, 0)) 
       
   254   If o (cond0, 
       
   255         Id(3, 0),
       
   256         If o (cond1, 
       
   257               Id(3, 0),  
       
   258               If o (cond2, 
       
   259                     Pdec2 o (Id(3, 0)),
       
   260                     If o (cond3, case3, Id(3, 0)))))
       
   261 }
       
   262 
       
   263 val Newright = {
       
   264   val cond0 = Eq o (Id(3, 2), Const(0))
       
   265   val cond1 = Eq o (Id(3, 2), Const(1))
       
   266   val cond2 = Eq o (Id(3, 2), Const(2))
       
   267   val cond3 = Eq o (Id(3, 2), Const(3))
       
   268   val case2 = Penc o (S o (Read o (Id(3, 0))), Id(3, 1))
       
   269   If o (cond0, 
       
   270         Write o (Const(0), Id(3, 1)),
       
   271         If o (cond1, 
       
   272               Write o (Const(1), Id(3, 1)),  
       
   273               If o (cond2, 
       
   274                     case2,
       
   275                     If o (cond3, Pdec2 o (Id(3, 1)), Id(3, 0)))))
       
   276 }
       
   277 
       
   278 val Actn = Swap (Pr(Pdec1 o (Pdec1 o (Id(1, 0))), Pdec1 o (Pdec2 o (Id(3, 2)))))
       
   279 
       
   280 val Action = {
       
   281   val cond1 = Noteq o (Id(3, 1), Z)
       
   282   val cond2 = Within o (Id(3, 0), Pred o (Id(3, 1)))
       
   283   val if_branch = Actn o (Ldec o (Id(3, 0), Pred o (Id(3, 1))), Id(3, 2))
       
   284   If o (Conj o (cond1, cond2), if_branch, Const(4))
       
   285 }
       
   286 
       
   287 val Newstat = Swap (Pr (Pdec2 o (Pdec1 o (Id(1, 0))),
       
   288                         Pdec2 o (Pdec2 o (Id(3, 2)))))
       
   289 
       
   290 val Newstate = {
       
   291   val cond = Noteq o (Id(3, 1), Z)
       
   292   val if_branch = Newstat o (Ldec o (Id(3, 0), Pred o (Id(3, 1))), Id(3, 2))
       
   293   If o (cond, if_branch, Z)
       
   294 }
       
   295 
       
   296 val Conf = Lenc (List(Id(3, 0), Id(3, 1), Id(3, 2)))
       
   297 
       
   298 val State = Ldec o (Id(1, 0), Z)
       
   299 
       
   300 val Left = Ldec o (Id(1, 0), Const(1))
       
   301 
       
   302 val Right = Ldec o (Id(1, 0), Const(2))
       
   303 
       
   304 val Step = {
       
   305   val left = Left o (Id(2, 0))
       
   306   val right = Right o (Id(2, 0))
       
   307   val state = State o (Id(2, 0))
       
   308   val read = Read o (right)
       
   309   val action = Action o (Id(2, 1), state, read)
       
   310   val newstate = Newstate o (Id(2, 1), state, read)
       
   311   val newleft = Newleft o (left, right, action)
       
   312   val newright = Newright o (left, right, action) 
       
   313   Conf o (newstate, newleft, newright)
       
   314  } 
       
   315 
       
   316 val Steps = Pr (Id(2, 0), Step o (Id(4, 1), Id(4, 3)))
       
   317 
       
   318 val Stknum = Minus o (Sigma1(Ldec o (Id(2, 1), Id(2, 0))) o (Enclen o (Id(1, 0)), Id(1, 0)),
       
   319                       Ldec o (Id(1, 0), Enclen o (Id(1, 0))))
       
   320 
       
   321 val Right_std = {
       
   322   val bound = Enclen o (Id(1, 0))
       
   323   val cond1 = Le o (Const(1) o (Id(2, 0)), Id(2, 0))
       
   324   val cond2 = All1_less (Eq o (Ldec o (Id(2, 1), Id(2, 0)), Const(1)))
       
   325   val bound2 = Minus o (Enclen o (Id(2, 1)), Id(2, 0))
       
   326   val cond3 = 
       
   327     (All2_less (Eq o (Ldec o (Id(3, 2), Add o (Id(3, 1), Id(3, 0))), Z))) o (bound2, Id(2, 0), Id(2, 1)) 
       
   328   Ex1(Conj o (Conj o (cond1, cond2), cond3)) o (bound, Id(1, 0))
       
   329 }
       
   330 
       
   331 val Left_std = {
       
   332   val cond = Eq o (Ldec o (Id(2, 1), Id(2, 0)), Z)
       
   333   (All1_less(cond)) o (Enclen o (Id(1, 0)), Id(1, 0))
       
   334 }
       
   335 
       
   336 val Std = Conj o (Left_std o (Left o (Id(1, 0))), Right_std o (Right o (Id(1, 0))))
       
   337 
       
   338 val Final = Eq o (State o (Id(1, 0)), Z)
       
   339 
       
   340 val Stop = {
       
   341   val stps = Steps o (Id(3, 2), Id(3, 1), Id(3, 0))
       
   342   Conj o (Final o (stps), Std o (stps))
       
   343 }
       
   344 
       
   345 val Halt = Mn (Not o (Stop o (Id(3, 1), Id(3, 2), Id(3, 0))))
       
   346 
       
   347 val UF = Pred o (Stknum o (Right o (Steps o (Halt o (Id(2, 0), Id(2, 1)), Id(2, 1), Id(2, 0)))))
       
   348 
       
   349 }