
Originally Posted by Zellski
There's an enormous amount of existing research (and algorithms) in the domain of global optimization. I haven't kept up with research but I did delve into it at some depth in the mid-90's for my thesis. This is a rather specialized problem, but it'll still benefit from an algorithm that cleverly avoids the 99.9999% of the search space that is clearly not interesting.
Basic approaches are simulated annealing (good for discrete problems such as this), sequential quadratic programming (perhaps better for continuous functions), genetic (or other evolutionary) algorithms. There's a whole field of combinatorial optimization / integer programming that I don't know much about. It's possible those approaches would be better suited to this specific problem.
Genetic algorithms have the great virtue of being very easy to implement (you mostly just have to calculate a fitness function for every possible state, which I'm sure you already have). If they seem to work well, you're done. They are notoriously difficult to analyze -- but for a pragmatic task like this, maybe that doesn't matter.
Is the implementation in C#?
|
Simulated annealing will only give you an approximation and quadratic programming won't work because the function to be optimized is not quadratic (it isn't linear either, although that's closer). You probably want nonlinear integer programming.
I've been doing some work on a gear/gem/reforging/enchant optimizer in my spare time. Let's take the very simple case of gear alone, ignoring all other factors (gemming and reforging are essentially the same optimization problems). The question we have to answer is this: given multiple item choices for each slot and a set of weights for each stat, can we find the optimal combination of items more efficiently than enumerating every possible item set and calculating the result of multiplying the stat weights by the sum of the stats on the items in each set? The number of item sets is the product of the number of item options you have for each slot, so it's easy to see that this blows up really quickly given sixteen slots and multiple items in each. Reforging is worse; with something like 6 reforging options per item, you're looking at something like 2.8 trillion reforging possibilities, were you to take a naive approach (although you can easily cut this down by not considering reforging into sub-optimal secondary stats excluding hit/exp).
If not for the hit and expertise caps, we absolutely could beat enumerating them all -- because the item values could then be calculated
independently. You could write a greedy algorithm that simply takes the item with the highest calculated score for each slot. Unfortunately this won't work, because the hit and expertise caps mean that item values can't be calculated independent of their set.
I spent a little time investigating solving this with 1-0 integer programming, as it is an instance of the set partitioning problem (by definition NP-Hard), but I don't think it is possible now. Even construction the decision matrix governing item inclusion in sets requires enumerating all sets and storing them in memory... The problem appears intractable. In the short-term, I'm going to implement a naive exhaustive search, which will give an optimum result, if inefficiently.
If you continue with this, I would recommend using a solver library, rather than attempting to roll your own algorithm. Try
Microsoft Solver Foundation - Express Edition - Home. Intuition tells me that this should be solved with an integer programming formulation similar to set partitioning, but I can't figure out how to make it work.
Something like:
Variables:
one variable per piece of gear, takes 0-1 value to indicate its presence in the set with the multiplier being the calculated value of that piece of gear (in a minimization problem, this would be the cost)
Constraints: 16, one for each slot (input matrix)
for each gear slot:
(x1 xor x2 xor x3 xor ... xor xn) to ensure we select one and only one piece of gear per slot (rings and trinkets are treated as one slot since we do that combination before optimization)