def createRandomWith(populationSize, targetFunction, maxDepth, functions, terms, bounds=[-5,5]):
     return Population([Program.random(maxDepth, functions, terms, bounds) for i in range(populationSize)], targetFunction)
 def mutate(parent, maxDepth, functions, terms):
     randomProgram = Program.random(int(maxDepth/2), functions, terms, [-5,5])
     randomNodeIndex = random.randint(0, randomProgram.nodeCount()-1)
     child = parent.copy()
     child.replaceAt(randomNodeIndex, randomProgram.subProgramAt(randomNodeIndex)[0])
     return Program.prune(parent, maxDepth, terms)