Guest User

Untitled

a guest
Feb 18th, 2018
90
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.53 KB | None | 0 0
  1. package kronecker
  2.  
  3. import spire.implicits._
  4.  
  5. /**
  6. * Utilities for doing diagonalization in N dimensions.
  7. *
  8. * The goal here is to be able to support diagonalizations for
  9. * arbitrary tuples, e.g. Tuple2, Tuple3, Tuple9, etc. The "dimension"
  10. * (or "dim") represents the arity of the tuple: dim=2 would
  11. * correspond to a Tuple2.
  12. *
  13. * We model each generated tuple as an "element" (a list of integers).
  14. * The individual integers in the element correspond to positions in
  15. * underlying streams of values, and the element corresponds to a
  16. * particular tuple.
  17. *
  18. * For example, if we have a type Ascii which corresponds to ASCII
  19. * strings, we might choose to represent the stream of all distinct
  20. * Ascii values as:
  21. *
  22. * "a", "b", ... "z", "aa", "ab", ... "ba", ... "zz", "aaa", ...
  23. *
  24. * In this case, we could represent the stream of all possible
  25. * Tuple2[Ascii, Ascii] values as:
  26. *
  27. * ("a", "a"), ("b", "a"), ("a", "b"), ("c", "a"), ("b", "b"), ...
  28. *
  29. * This would correspond to the elements:
  30. *
  31. * (0, 0), (1, 0), (0, 1), (2, 0), (1, 1), ...
  32. *
  33. * (where the integers index into the original stream of ASCII string
  34. * values above.)
  35. *
  36. * Here are some worked examples to get an idea of what is going on
  37. * with the indices. Each row of text here represents a "depth"
  38. * (depth=0 is the first row), and each logical column represents a
  39. * "position" at that depth. The "width" at a given depth is the
  40. * number of columns at that depth; for dim=1, width is always 1.
  41. *
  42. * dim=1
  43. * 0
  44. * 1
  45. * 2
  46. * 3
  47. *
  48. * dim=2
  49. * (0 0)
  50. * (1 0) (0 1)
  51. * (2 0) (1 1) (0 2)
  52. * (3 0) (2 1) (1 2) (0 3)
  53. * ...
  54. *
  55. * dim=3
  56. * (0 0 0)
  57. * (1 0 0) (0 1 0) (0 0 1)
  58. * (2 0 0) (1 1 0) (1 0 1) (0 2 0) (0 1 1) (0 0 2)
  59. * (3 0 0) (2 1 0) (2 0 1) (1 2 0) (1 1 1) (1 0 2) (0 3 0) (0 2 1) (0 1 2) (0 0 3)
  60. * ...
  61. *
  62. * and so on.
  63. *
  64. * The advantage of using Diagonal.atDepth is that it doesn't require
  65. * calculating all the preceeding elements in order to calculate an
  66. * element. This doesn't seem like a big deal until you consider that
  67. * at depth 30 a 20-tuple has over 47 trillion distinct elements.
  68. */
  69. object Diagonal {
  70.  
  71. type Elem = List[Z]
  72.  
  73. /**
  74. * Determine how many elements of dimension `dim` exist at a given
  75. * tree `depth`.
  76. *
  77. * widthAtDepth(0, d) = 1
  78. * widthAtDepth(1, d) = d + 1
  79. * widthAtDepth(2, d) = ((d+1) * (d+2)) / 2
  80. * widthAtDepth(3, d) = ((d+1) * (d+2) * (d+3)) / 6
  81. * ...
  82. */
  83. def widthAtDepth(dim: Int, depth: Z): Z = {
  84. def loop(i: Int, term: Z, num: Z, denom: Z): Z =
  85. if (i <= 0) num / denom
  86. else loop(i - 1, term + 1, (depth + term) * num, denom * term)
  87. loop(dim, Z.one, Z.one, Z.one)
  88. }
  89.  
  90. /**
  91. * Find a dimension `dim` element at the given `depth` denoted by
  92. * position `pos`.
  93. *
  94. * Requirement: 0 <= pos < widthAtDepth(dim, depth)
  95. */
  96. def atDepth(dim: Int, depth: Z, pos: Z): Elem = {
  97. require(dim >= 1, s"($dim >= 1) was false")
  98. require(depth >= 0, s"($depth >= 0) was false")
  99. val w = widthAtDepth(dim, depth)
  100. require(0 <= pos && pos < w, s"(0 <= $pos && $pos < $w) was false")
  101. atDepth0(dim, depth, pos)
  102. }
  103.  
  104. /**
  105. * Same as atDepth but without the input validation.
  106. */
  107. def atDepth0(dim: Int, depth: Z, pos: Z): Elem =
  108. dim match {
  109. case 1 =>
  110. depth :: Nil
  111. case d =>
  112. def loop(curr: Z, dp: Z): (Z, Z) = {
  113. val w = widthAtDepth(dim - 1, dp)
  114. val next = curr - w
  115. if (next >= 0) loop(next, dp + 1) else (curr, dp)
  116. }
  117. val (pos2, depth2) = loop(pos, 0)
  118. val elem = depth - depth2
  119. elem :: atDepth(dim - 1, depth2, pos2)
  120. }
  121. }
Add Comment
Please, Sign In to add comment