def bestMutation(shape, model, cycles=50, startHeat=100, heatDiv=1.01, alpha=.5):
    """
    Mutates a shape for a given number of cycles and returns the best scoring change
    :param shape: The shape to mutate
    :param model: The model object
    :param cycles: The number of cycles (attempts at mutation)
    :param startHeat: The initial maximum random number which a point can change by
    :param heatDiv: The amount to divide the heat by every time the shape mutates into a better position
    :param alpha: The alpha value to use when calculating color
    :return: An array representing the best change. [score, color, replacement, bounds]
    """

    bestShape = shape
    score, color, replacement, bounds = model.scoreShape(bestShape, alpha)
    bestChange = [score, color, replacement, bounds]

    curHeat = startHeat

    for j in range(cycles):
        bestShape.mutate(heat=curHeat)

        score, color, replacement, bounds = model.scoreShape(bestShape, alpha)
        change = [score, color, replacement, bounds]

        if score > bestChange[0]:
            bestChange = change
            curHeat = int(curHeat / heatDiv)
            curHeat = max(curHeat, 10)
        else:
            bestShape.undoMutate()


    return bestChange