The full code for Milestone 1 can be found here. Code has since be updated to the final version, and will no longer produce the results seen to the left.
In order to advance my understanding in multiple areas, I thought it would be best to do some of the work manually, as well as experiment with having Gemini handle certain parts. To be specific, I created all of the logic managing the actual genetic algorithm, while Gemini made the visuals, because I am avoiding front-end like the plague.
The attached code is based on the provided example, but with many changes. Beyond the visuals, I introduced a new feature: a target to be evolved toward (seen on the bottom row), and altered both the selection and crossover logic to center around this new goal. Rather than accepting user input via the mouse hovering over an image to judge fitness, the program now calculates Euclidean Distance between the DNA of each candidate and that of the target. That distance becomes the fitness, with a lower score being more desirable. As such, I then sort the list of finesses, and select the two closest to the target. These become the parents of the next generation. The crossover process has also been altered. Rather than taking half of each of the DNA of each parent, this takes whichever parent's DNA is closer to our desired value. This is not a perfect system by any mean, as it is possible for there to be a single universally best example that carries over into the next generation without modification. In that case, we will be relying on the mutation rate, which probably should be increased anyway for this methodology.
Final Product
Per Professor St. John's suggestion, I experimented with using Gemini for this project. The complete transcription of the conversation, pertaining both to Milestone 1 and the final product, is available to the right. This document is exhaustive and rather verbose so below is an overview of the second, which concerns changes made after Milestone 1:
The logic in Milestone 1 was reliant on the selection of an arbitraty goal to evolve toward. That did not seem feasible for the final product, simply because I didn't like the idea of randomly selecting music to iterate toward, as it could result in selecting something highly displeasing to the user. Additonally, the final product had to include an interactive element. Thus, I discussed implementing the following changes with Gemini:
First, the UI was modified to be of a similar form to the starting code, with minor variations. Specifically, this involved removing the target box and associated code. Additonally, the previous logic for user input was thrown out. Previously, the starter code had relied on the user 'rolling over' their mouse on a particular box, with the eventual fitness score being determined by the amount of time spent over that item. I didn't really like this, both due to being time consuming and resulting in fitness scores that could be wildly out of scale with one another. Instead, I favored a simlpe 1-5 score system.
The part I was least familiar with, going into this process, was the tecnology/modules to actually play a sound on the user's computer. While I have worked with UI and graphics before, albeit in other languages, audio was something totally new to me. This seemed like a great opportunity to use Gemini. I initially asked it about various different ways to produce this effect and then had it generate the relevant code.
Much of my conversation with Gemini was ultimately bug fixing. The initial code it generated basically didn't work at all and required numerous updates to get to a both visually and auditorially functional state. The vast majority of the length of the attached document is Gemini returning the same code with slight variations. The biggest issue I ran into was ultimately an issue of scope. When I initially prompted Gemini to generate a section of code, I provided it a base to work from, including a combination of the starter code and my own modifications. Towards the end of my conversation, I ran into a problem that Gemini seemed to be struggling to deal with. After reading back through the code, the issue was arising from an area of the code that I had not given Gemini. I did not, at least at first, give it the full text of the DNA class, as I didn't think it needed to modify anything in there. However, this meant that it lacked certain context on how some of the functions called in code it was using worked. This resulted in a variety of strange errors that were ultimaetly fixed by a minor modification to the function in question.
Final Reflection