Greetings!
My hope with this thread is to get some advice on improving the solving performance of the attached program as well as providing it as inspiration for other ideas. It is quite developed (please excuse the messy code, this is a mad science research project at this point) and complex.
The main concept of my model is a domino effect of tasks where the first task type is required to happen and has a negative effect on a reservoir. This requires the model to enable an optional task of the next task type to have a positive effect on the reservoir. The reservoirs are done by first outlining the inactive time slices around the intervals to then infer the actives are the inverse time slices on the timeline. This is done because you cannot go through all optional intervals and say that if variable at time t is active for a particular machine that time t must be between the start and end of all intervals for that machine. You can, however, say that all inactive variables must be either before or after all intervals for a particular machine and say that the sum(inactives) == horizon - sum(durations) where sum(durations) is total time running so horizon - sum(durations) is time not running. Each task is linked to tank task so that if machine and tank are active at time t, then there is a machine&tank active (plus time and effect) being applied to a reservoir representing the tank. This, I believe, is where the complexity of my model comes in because there are multiple machines, each of which has multiple tanks they can theoretically go to. So you have n*m machine active and inactive variables plus n*t tank active and inactive variables plus n*m*t machine&tank active variables where n is the number of time slices, m is the number of machines and t is the number of tanks. All of that is per the product type, or formula because the machines process differently per product type.
All of those variable arrays of actives per machine are effectively n choose k so something that yielded a good performance improvement was saying that machine must be active a specific minimum time and then computing all n choose k combinations that have groupings of 3 or more of active variables. This reduced the difficulty from 16 million combinations to 98 thousand. I do this on lines 380->390 where a small section of multithreaded code computes all of the combinations to be used later in AddAllowedAssignments for each machine's set of active variables.
There are many commented out "model.Add..." statements that were constraints I tested by performing empirical analysis over multiple runs.
I have tried using hints but because of the relatively drastic changes in the solution when adding more formulas the hints degraded performance. It would make sense to use hint between task types but the program right now is only considering the first Equip=>Tank, Tank=>Equp relationship and its struggling where if the model becomes feasible to fully scale-out it will have 5 task=>tank=>task relationships.
As the program stands now, I believe the only libraries I'm using that aren't standard in python are ortools and matplotlib (for a gantt chart of the solution).
I hope to get input on ways to improve my model's performance because as it sits right now I cannot scale it up without an exponential increase in solving time. I also hope to get feedback on how quickly it solves on more resource equipped machines. Right now I only have access to a 2c/4t machine that has the best performance using 4 workers and a 6c/12t machine that performs best with 6 workers (using more workers degrades performance, probably due to limits of the hyperthreading architecture on this particular machine?) I hope to run this on a well equipped AWS EC2 instance soon but I don't have that set up yet.
I feel like I'm kind of at a dead-end beyond trying to change the search type but I'm not sure where I can find all the values that search_branching can take and changing search_branching doesn't seem to work with multiple workers? If anyone can explain this or point me to some documentation on changing the search types and getting that to work with multiple workers that would be awesome!
I average 55.6s using 4 workers and 52.6s using FIXED_SEARCH which seems for force 1 worker... These can be commented in and out at lines 682-691
I know this is a lot....but any and all input is welcome!
Thanks!