Guest User

Untitled

a guest
Jul 20th, 2018
120
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.57 KB | None | 0 0
  1. from random import random, randint, choice
  2. from copy import deepcopy
  3. from math import log
  4.  
  5. class fwrapper:
  6. def __init__(self, function, childcount, name):
  7. self.function = function
  8. self.childcount = childcount
  9. self.name = name
  10.  
  11. class node:
  12. def __init__(self, fw, children):
  13. self.function = fw.function
  14. self.name = fw.name
  15. self.children = children
  16.  
  17. def evaluate(self, inp):
  18. results = [n.evaluate(inp) for n in self.children]
  19. return self.function(results)
  20.  
  21. def display(self, indent = 0):
  22. # output as lisp code
  23. print((' ' * indent) + '(' + self.name)
  24. for c in self.children:
  25. c.display(indent + 1)
  26. print(')')
  27.  
  28. class paramnode:
  29. def __init__(self, idx):
  30. self.idx = idx
  31.  
  32. def evaluate(self, inp):
  33. return inp[self.idx]
  34.  
  35. def display(self, indent = 0):
  36. # output as lisp code
  37. print('%sp%d' % (' ' * indent, self.idx))
  38.  
  39. class constnode:
  40. def __init__(self, v):
  41. self.v = v
  42.  
  43. def evaluate(self, inp):
  44. return self.v
  45.  
  46. def display(self, indent = 0):
  47. # output as lisp code
  48. print('%s%d' % (' ' * indent, self.v))
  49.  
  50. def makerandomtree(pc, maxdepth = 10, fpr = 0.5, ppr = 0.6):
  51. flist = [
  52. fwrapper(lambda l:l[1] if l[0] != 0 else l[2], 3, 'if'),
  53. fwrapper(lambda l:1 if l[0] > l[1] else 0, 2, '>'),
  54. fwrapper(lambda l:1 if l[0] < l[1] else 0, 2, '<'),
  55. fwrapper(lambda l:l[0] + l[1], 2, '+'),
  56. fwrapper(lambda l:l[0] - l[1], 2, '-'),
  57. fwrapper(lambda l:l[0] * l[1], 2, '*'),
  58. # ignore division as it brings too much trouble
  59. ]
  60.  
  61. if random() < fpr and maxdepth > 0:
  62. f = choice(flist)
  63. children = [makerandomtree(pc, maxdepth - 1, fpr, ppr)
  64. for i in range(f.childcount)]
  65. return node(f, children)
  66. elif random() < ppr:
  67. return paramnode(randint(0, pc - 1))
  68. else:
  69. return constnode(randint(0, 10))
  70.  
  71. def hiddenfunction(x, y):
  72. # the truth of the nature
  73. return x**2 + y**2 + 1
  74.  
  75. def buildhiddenset():
  76. # observed phenomenons
  77. rows = []
  78. for i in range(1000):
  79. x = randint(0, 100)
  80. y = randint(0, 100)
  81. rows.append([x, y, hiddenfunction(x, y)])
  82. return rows
  83.  
  84. def scorefunction(tree, s):
  85. dif = 0
  86. for data in s:
  87. v = tree.evaluate([data[0], data[1]])
  88. dif += abs(v - data[2])
  89. return dif
  90.  
  91. def mutate(tree, pc, probchange = 0.3):
  92. if random() < probchange:
  93. return makerandomtree(pc)
  94. else:
  95. result = deepcopy(tree)
  96. if isinstance(tree, node):
  97. result.children = [mutate(c, pc, probchange)
  98. for c in tree.children]
  99. return result
  100.  
  101. def crossover(tree1, tree2, probswap = 0.7, top = 1):
  102. if random() < probswap and not top:
  103. return deepcopy(tree2)
  104. else:
  105. result = deepcopy(tree1)
  106. if isinstance(tree1, node) and isinstance(tree2, node):
  107. result.children = [crossover(c, choice(tree2.children), probswap, 0)
  108. for c in tree1.children]
  109. return result
  110.  
  111. def evolve(pc, popsize, rankfunction, maxgen = 500, mutationrate = 0.1, breedingrate = 0.4, pexp = 0.7, pnew = 0.05):
  112. def selectindex():
  113. # equivalent to log_pexp^random(), function value from zero to infinity
  114. return int(log(random())/log(pexp))
  115.  
  116. population = [makerandomtree(pc) for i in range(popsize)]
  117. for i in range(maxgen):
  118. scores = rankfunction(population)
  119. print(scores[0][0])
  120. if scores[0][0] == 0:
  121. break
  122.  
  123. # at least we need a couple
  124. newpop = [scores[0][1], scores[1][1]]
  125. while len(newpop) < popsize:
  126. if random() > pnew:
  127. # breed
  128. newpop.append(
  129. mutate(
  130. crossover(
  131. scores[min(selectindex(), len(scores) - 1)][1],
  132. scores[min(selectindex(), len(scores) - 1)][1],
  133. probswap = breedingrate),
  134. pc, probchange = mutationrate))
  135. else:
  136. # make new out of void
  137. newpop.append(makerandomtree(pc))
  138. population = newpop
  139. scores[0][1].display()
  140. return scores[0][1]
  141.  
  142. def getrankfunction(dataset):
  143. def rankfunction(population):
  144. scores = [(scorefunction(t, dataset), t)
  145. for t in population]
  146. scores = sorted(scores, key=lambda x: x[0])
  147. return scores
  148. return rankfunction
  149.  
  150. evolve(2, 300, getrankfunction(buildhiddenset()), 500, 0.3, 0.3, 0.2, 0.2)
Add Comment
Please, Sign In to add comment