Search Unity

Discussion Avoid evolutionary algorithm approaching an arbitrary average

Discussion in 'Scripting' started by Shack_Man, Dec 29, 2022.

  1. Shack_Man

    Shack_Man

    Joined:
    Jun 7, 2017
    Posts:
    372
    First of all thanks for clicking this despite the horrible title....

    So I have creatures with a color value (hue) of 0 to 1, and since hue is a nice circle 1.1 will be treated as 0.1 etc. Now I want them to breed, 2 at a time and take the average color. But of course adding 2 random values between 0 and 1 and dividing by 2 will gravitate towards 0.5. Like rolling 2 dice and adding the numbers: 2 and 12 will have a much lower chance than 7.


    Any suggestions how to avoid this? Clearly I need something better than adding both values and divide by 2. Right now I simply take only one of the values and apply a random mutation of 5%.
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,686
    You mention "evolutionary algorithm" but I did not see any discussion of a fitness function, specifically one that selects based on the phenotype in question (color).

    Without a fitness function, evolution does not happen. It's just randomness that drifts around at the rate of mutation.

    The presence of a fitness function guides development to more-fit individuals.
     
    AnimalManUK and Yoreki like this.
  3. Shack_Man

    Shack_Man

    Joined:
    Jun 7, 2017
    Posts:
    372

    Wow, thanks for the video! I think my question wasn't clear enough though, averaging colors is not an issue, or rather, I want to avoid it. I'll do more research and update this thread. As for your methods, iirc you can just use (color1 + color2)/2f.
     
  4. Shack_Man

    Shack_Man

    Joined:
    Jun 7, 2017
    Posts:
    372

    The predators detect the creatures based on the color difference to their surrounding, that's where the evolution happens. Even with total random color mutation, they will eventually blend into the environment.
     
  5. Shack_Man

    Shack_Man

    Joined:
    Jun 7, 2017
    Posts:
    372
    I can tell you like evolution and your name isn't a coincidence :)

    I'll try to express my problem (actually expressing it is the difficult part, otherwise I could google an answer):

    I start with a lot of creatures and their colors are totally random. When 2 of them mate, their offspring will be an average of them. If I express the color as a range between 0 and 1, or in RGB 3 values between 0 and 255, the population will sooner or later become 0.5f or (127, 127, 127).
    I called it arbitrary because that just happens to be the numbers assigned to colors when computer graphics were invented. If you tell this scenario to someone without any knowledge, they wouldn't say that clearly the creatures become grey (rgb 127, 127, 127) or cyan (hue 0.5f).

    I guess that's just very simple math/logic. But is there a way to have the colors stay diverse, yet based on both parents? What I do right now is take the color only from one of the parent's and then apply a tiny bit of mutation that could go either way. Interestingly, because the creatures are capable of exponential growth, one color sooner or later takes over. So I make the simulation run itself over and over and I get a nicely distributed color wheel.
     
  6. chemicalcrux

    chemicalcrux

    Joined:
    Mar 16, 2017
    Posts:
    720
    The Great 127-ening does appear to occur, given a little experiment:

    Code (CSharp):
    1. import random
    2. colors = [random.uniform(0, 1) for x in range(100)]
    3.  
    4. for _ in range(10000):
    5.     c1, c2 = random.sample(colors, 2)
    6.     c = (c1 + c2) / 2
    7.     colors.append(c)
    upload_2022-12-30_14-21-32.png

    The problem is that are way too many ways to make 0.5

    Code (csharp):
    1.  
    2. samples = []
    3.  
    4. for c1 in range(0, 100, 1):
    5.   for c2 in range(0, 100, 1):
    6.     samples.append((0.01 * c1 + 0.01 * c2) / 2)
    7.  
    8. plt.hist(samples)
    9.  
    upload_2022-12-30_14-6-44.png

    It's extremely difficult to make red: both parents must be red!

    I think the idea above -- to use red, green, and blue separately -- is a step in the right direction.

    Code (csharp):
    1.  
    2. import itertools
    3. import colorsys
    4.  
    5. steps = 6
    6. values = [x * (1 / (steps - 1)) for x in range(steps)]
    7. colors = []
    8.  
    9. for _ in range(100):
    10.   colors.append([random.uniform(0, 1) for _ in range(3)])
    11.  
    12. for _ in range(10000):
    13.   c1, c2 = random.sample(colors, 2)
    14.   c = [0,0,0]
    15.  
    16.   for i in range(3):
    17.     c[i] = (c1[i] + c2[i]) / 2
    18.  
    19.   samples.append(c)
    20.  
    21. plt.hist(samples)
    22.  
    It starts out okay at like 1,000 samples, but it gets wonky at larger runtimes. Note that the position of the peak is reasonably random...so maybe that's workable for you?

    upload_2022-12-30_14-20-57.png

    I think the underlying problem here is that hue does not having a meaningful minimum and maximum value: it wraps around. It makes perfect sense for the average value to approach 50% if you have a random starting population and no selection pressure; conversely, 50% hue is a completely arbitrary point on the color wheel.

    Storing RGB values helps to get away from this. There is no one hue that's attracted towards -- instead, it trends towards 50% value. Instead of doing RGB, you could have a set of genes, each of which mixes a certain color into the creature's body.
     

    Attached Files:

    AnimalManUK likes this.
  7. Shack_Man

    Shack_Man

    Joined:
    Jun 7, 2017
    Posts:
    372

    I'll message you when I have a video. Actually the end goal of this is more about making a video/source code than a game. That way I can spent almost all of the time playing around with evolution systems and leave out the whole game design/usability etc.
     
  8. Shack_Man

    Shack_Man

    Joined:
    Jun 7, 2017
    Posts:
    372
    Thanks for the graphs, I'll go through it tomorrow with a clear head, just wrapping up a long coding day!
     
    chemicalcrux likes this.
  9. Shack_Man

    Shack_Man

    Joined:
    Jun 7, 2017
    Posts:
    372

    Yeah that's exactly my point. If I do the same with e.g. moving speed, that is not arbitrary at all and starting with values from 0 to 1 gravitating towards 0.5 makes a lot more sense.
     
  10. All_American

    All_American

    Joined:
    Oct 14, 2011
    Posts:
    1,528
    @Shack_Man

    I’ve been working with genetic algorithms and like Kurt said you’re going to want to use a fitness score….or some sort of “Elitism” type score. That’s how I would do it…..then you can punish the lower scores with a color that gets murdered quicker….?
     
  11. Shack_Man

    Shack_Man

    Joined:
    Jun 7, 2017
    Posts:
    372

    If it were only about numbers, sure, but why leave out the entire dynamic interactions that Unity can offer (which I'd guess is much closer to mimicking natural selection).
     
  12. All_American

    All_American

    Joined:
    Oct 14, 2011
    Posts:
    1,528
    What I meant was use the score to control the colors. Instead of having them derive from the parents they can be slightly different. Using the score to have a better color to have a better chance of survival and to have a better match for reproduction and then create better offspring.

    instead of using the colors of the parents that would end up being blah…..use the parents color that has the better score as the driver of the offsprings color.