I posted this question earlier on stackoverflow, where it was closed as off-topic. I hope it survives here.
I our climbing gym, the routes need to be re-set from time to time. The following rules apply:
- We have climbing holds with a number of different colors in varying quantities. - When a route is set in a sector, no other route with the same color must be set in that sector or in the nearby sectors to avoid confusion.
- Some color combinations must be avoided in a sector, like white/gray or red/pink.
- The goal is to have four routes in each sector, less is ok if four would break the above rules.
I have tried two different approaches by now. The first one was Simulated Annealing where I initialized the wall with a random pattern of colors (but with a given color weight) and computed a badness for each color combination. This badness was also computed for combinations between one sector and its neighbours. In each iteration a randomly chosen route from the worst sector was swapped with a route from a randomly chosen other sector. This showed some sort of convergence, but the result was not usable (i.e. the resulting state contained sectors with double or triple colors).
I then approached the problem from the opposite side and started with an empty wall. This time, every color had a concentration which decayed from one sector to the adjacent sectors. The concentration of similar colors was also increased, i.e. a red route increased the concentration of orange in a sector and nearby. A weighted random source of colors (the bucket) gave me the next color for the wall, which was placed at the sector with the lowest concentration of this color. If a concentration was above a certain threshold, the color was not added (but put back into the bucket). This was a partial success because the result state did not contain any double colors - but some sectors were empty or contained only one color.
So: What could be an appropriate algorithm for solving this problem, given the above rules? I'll happily add more information when required.
Edit 1 - More information:
- my test case has 15 sectors,
- each sector should contain 4 routes
- the real gym has 3 buildings with an average of 50 sectors each
- some sectors are arranged around pillars, some are connected by roofs
- we have about 10 different hold colors
- the height of the sectors varies between 6 (beginner's section) and 20 meters (13 vertical + 7 roof), so they consume different amounts of holds. However, the average is about 12 and this can be considered constant.
- there is a limited amount of each color, the amounts are not equal
- some colors are easier, some more difficult (i. e. we can create a yellow route of any difficulty, whereas creating a very easy orange route for kids will be almost impossible)
- some sectors are "easier", so easy colors should go there (this is optional, our route setters can make things harder or easier within a wide range).
- we can safely say which colors go well together in a sector or in neighbouring sectors and which combinations don't. There are some surprises, such as white and black (bad combo): both turn to gray while rubber (shoes) or chalk (hands) is left on them.
- some hold colors are combinations like violet/white (in a stripey pattern).
Edit 2: Some Questions about Genetic Algorithms
I now downloaded and compiled ParadisEO and even got my IDE (I'm using Code::Blocks) to compile the QuickStart example. ParadisEO offers genetic algorithms with a single objective as well as multi-objective GA. GertVdE suggested to calculate the fitness of each sector and to maximize the sum of all sectors' fitnesses as a single objective. Could I also maximize the fitness of each sector with a multi-objective GA? That would be some 50 objectives.
Also, I'm struggling with the definition of a sensible crossover function. As the maximum amount of each color is fixed, crossing can lead to illegal states. If I allow more than the previously given maximum amount, the overall pattern might converge to a repitition of less "toublesome" combinations where the troublesome colors have been thrown out. On the other hand I can also throw out excess colors until the maximum is reached, making the crossover function non-conservative.
(I am completely new to genetic algorithms)