Guest User

Untitled

a guest
Jun 23rd, 2018
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.12 KB | None | 0 0
  1. discard """
  2. 遺伝的アルゴリズムで OneMax問題 を解く
  3.  
  4. 2018/06/23
  5.  
  6. (c) 2018 kapifuji
  7. """
  8.  
  9. import random, system, algorithm, sequtils
  10. # random を使用する際、これがないと毎回同じ値が生成される
  11. randomize()
  12.  
  13. # ランダムな遺伝子を得る
  14. proc getRandomGenom(length: uint): seq[int8] =
  15. var genom: seq[int8] = @[]
  16.  
  17. for i in 1..length:
  18. genom.add(random.rand(1).toU8)
  19.  
  20. result = genom
  21.  
  22. # 遺伝子を評価する
  23. proc evaluateGenom(genom: seq[int8]): float =
  24. var sum = 0
  25.  
  26. for i, value in genom:
  27. sum += value
  28.  
  29. result = sum / genom.len
  30.  
  31. # 親となる遺伝子を選択する
  32. proc selectGenom(genomList: seq[seq[int8]], length: uint): seq[seq[int8]] =
  33. var selectedGenomList = genomList
  34.  
  35. selectedGenomList.sort(proc (x, y: seq[int8]): int = system.cmp(y.evaluateGenom, x.evaluateGenom))
  36.  
  37. result = selectedGenomList[0..(length - 1)]
  38.  
  39. # 遺伝子を交叉させる
  40. proc crossoverGenom(genom1, genom2: seq[int8]): tuple[first: seq[int8], second: seq[int8]]=
  41. var
  42. first: seq[int8] = genom1
  43. second: seq[int8] = genom2
  44. let
  45. point1 = random.rand(genom1.high)
  46. point2 = random.rand(point1..genom1.high)
  47.  
  48. sequtils.delete(first, point1, point2)
  49. sequtils.delete(second, point1, point2)
  50. sequtils.insert(first, genom2[point1..point2], point1)
  51. sequtils.insert(second, genom1[point1..point2], point1)
  52.  
  53. result = (first, second)
  54.  
  55. # 次世代の遺伝子リストを得る(現行の遺伝子リストから低評価遺伝子を子孫と入れ替える)
  56. proc getNextGenomList(genomList, progenyGenomList: seq[seq[int8]]): seq[seq[int8]] =
  57. var nextGenomList: seq[seq[int8]] = genomList
  58.  
  59. nextGenomList.sort(proc (x, y: seq[int8]): int = system.cmp(x.evaluateGenom, y.evaluateGenom))
  60. sequtils.delete(nextGenomList, 0, progenyGenomList.high)
  61. nextGenomList.add(progenyGenomList)
  62.  
  63. result = nextGenomList
  64.  
  65. # 突然変異を適用
  66. proc mutateGenom(genom: seq[int8], individualMutation, genomMutation: float): seq[int8] =
  67. var mutatedGenom: seq[int8] = genom
  68.  
  69. if individualMutation > random.rand(100.0):
  70. for i, value in mutatedGenom:
  71. if genomMutation > random.rand(100.0):
  72. mutatedGenom[i] = random.rand(1).toU8
  73.  
  74. result = mutatedGenom
  75.  
  76. # 始めの遺伝子リストを作る
  77. proc getInitialGenom(genomLength, genomListLength: uint): seq[seq[int8]] =
  78. var genomList: seq[seq[int8]] = @[]
  79.  
  80. for i in 1..genomListLength:
  81. genomList.add(getRandomGenom(genomLength))
  82.  
  83. result = genomList
  84.  
  85. # 子孫となる遺伝子のリストを得る
  86. proc getProgenyGenom(selectedGenomList: seq[seq[int8]]): seq[seq[int8]] =
  87. var progenyGenomList: seq[seq[int8]] = @[]
  88.  
  89. for i in 0..selectedGenomList.high:
  90. let
  91. first = selectedGenomList[i]
  92. second =
  93. if i == selectedGenomList.high: selectedGenomList[0]
  94. else: selectedGenomList[i + 1]
  95. progenyGenoms = crossoverGenom(first, second)
  96.  
  97. progenyGenomList.add(progenyGenoms.first)
  98. progenyGenomList.add(progenyGenoms.second)
  99.  
  100. result = progenyGenomList
  101.  
  102. # 突然変異を適用した遺伝子リストを得る
  103. proc getMutateGenomList(genomList: seq[seq[int8]], individualMutation, genomMutation: float): seq[seq[int8]] =
  104. var mutatedGenomList = genomList
  105.  
  106. for i, genom in mutatedGenomList:
  107. mutatedGenomList[i] = genom.mutateGenom(individualMutation, genomMutation)
  108.  
  109. result = mutatedGenomList
  110.  
  111. # 遺伝子の評価値リストを得る
  112. proc getEvaluationList(genomList: seq[seq[int8]]): seq[float] =
  113. var evaluationList: seq[float] = @[]
  114.  
  115. for i, genom in genomList:
  116. evaluationList.add(genom.evaluateGenom)
  117.  
  118. result = evaluationList
  119.  
  120. # 結果の表示
  121. proc viewResult(genomList: seq[seq[int8]], generation: uint) =
  122. var
  123. sortedGenomList = genomList
  124. sum = 0.0
  125.  
  126. let
  127. evaluations = genomList.getEvaluationList
  128. minEvaluation = evaluations.min
  129. maxEvaluation = evaluations.max
  130.  
  131. sortedGenomList.sort(proc (x, y: seq[int8]): int = system.cmp(y.evaluateGenom, x.evaluateGenom))
  132. for j, value in evaluations:
  133. sum += value
  134.  
  135. let averageEvaluation = sum / evaluations.len.toFloat
  136.  
  137. echo ">>> generation " & $generation & " <<<"
  138. echo "min: " & $minEvaluation
  139. echo "max: " & $maxEvaluation
  140. echo "avg: " & $averageEvaluation
  141. echo "optimumGenom -> " & $sortedGenomList[0] & "\n"
  142.  
  143. proc main =
  144. const
  145. # 遺伝子の長さ
  146. GenomLength = 100
  147. # 個体の数
  148. GenomListLength = 100
  149. # 親となる個体の数(子孫はこの2倍生成される)
  150. SelectGenomLength = 20
  151. # 個体の突然変異確率 [%]
  152. IndividualMutation = 1
  153. # 遺伝子の1要素の突然変異確率 [%]
  154. GenomMutation = 1
  155. # 世代数
  156. Generation = 100
  157.  
  158. # 初期の遺伝子
  159. var genomList = getInitialGenom(GenomLength, GenomListLength)
  160.  
  161. for i in 1..Generation:
  162. # 結果の出力
  163. viewResult(genomList, i.uint)
  164.  
  165. # 選択、交叉と変異、世代交代
  166. let
  167. selectedGenomList = genomList.selectGenom(SelectGenomLength)
  168. progenyGenomList = selectedGenomList.getProgenyGenom.getMutateGenomList(IndividualMutation, GenomMutation)
  169. nextGenomList = getNextGenomList(genomList, progenyGenomList)
  170.  
  171. # 次の世代へ
  172. genomList = nextGenomList
  173.  
  174. when isMainModule:
  175. main()
Add Comment
Please, Sign In to add comment