Dwarf-Therapist / Dwarf-Therapist

Dwarf management tool for Dwarf Fortress
Other
621 stars 55 forks source link

Optimizer Enhancement: Labor Exclusions #163

Open qdbp opened 5 years ago

qdbp commented 5 years ago

I love the optimizer, but I believe one big deficiency is the inability to specify that certain labors should be mutually incompatible (or mutually required).

Use case examples:

I think this would be a valuable addition for fort organization.

cvuchener commented 5 years ago

The optimizer algorithm already do exclusions for conflicting jobs like miner/wood cutter/hunter. So the algorithm shouldn't be too hard to adapt. The difficulty would be more in designing the GUI. I wonder if, like the conflicting jobs, this should be a more global setting (i.e. affecting the grid view too).

skilled dwarves are sensitive and should not have burial

This is getting more specific and complex. If you could use a custom role for burial (eventually a scripted one), would that solve the issue? I don't think you use custom roles for hauling in the current optimizer.

Or optimize without that constraint, then apply a custom filter and disable burial for every one.

I want to have a dedicated doctor cadre: doctoring professions should mandate one another and exclude all others

Adding super labors in the optimizer, and the ability to a make (super) labors exclusive to everything else would solve that, maybe?

qdbp commented 5 years ago

Super labors in the optimizer was another thing I really wanted, so it's good that it's aligned with this issue.

As far as the GUI goes: I am not sure if anything is needed in the grid view to start. For the optimization plan editor, the most natural presentation to me is: an additional column, with a checklist-dropdown for each labour row indicating exclusions. Since exclusions are symmetric, corresponding checklists in the excluded labours would be automatically updated. A blue highlight indicating where any exclusions have been set (that differ from defaults) would be useful. I haven't worked with GUI code so I don't know if that is labour intensive.

P.S. I was wondering if a general power-up of the optimizer could be achieved by switching to something like an integer programming solver rather than the current algorithm?

P.P.S. What is the reason hauling labours are treated differently? My fort had a spell of trouble because slowpoke wood haulers got caught in an ambush and jittery wrecks went to bury them. I'd love to be able to assign strong, fast dwarves to haul stone, the emotionally stunted to burial, etc. And further restrict the numbers of each type of hauler.

cvuchener commented 5 years ago

I am not the author of the optimizer and I don't use it when playing so I don't know it very well.

A "checklist-dropdown" may be possible by tweaking the model and the view of a QComboBox. I have never done it and I am not sure how difficult it is. But the list of labors is long, I don't think it would be easy to use in a drop-down. I was thinking of a separate list view (or tree view, since it's a list of list), for building groups of mutually exclusive labors, selected either by the current context menu or drag-and-drop. Or maybe a list of pairs would easier?

P.S. I was wondering if a general power-up of the optimizer could be achieved by switching to something like an integer programming solver rather than the current algorithm?

We're maximizing the sum of role ratings? I guess it is a integer (or more exactly zero-one) linear programming problem then. I've used glpk for this kind of problem before, so It is not an issue. Although it would add a dependency for building DT. I need to check how annoying it is to build on Windows with MSVC.

I think the current solver is some kind of greedy algorithm who could do with some improvements. It has been reported to give weird results (#112), but I did not reproduce them myself.

P.P.S. What is the reason hauling labours are treated differently? My fort had a spell of trouble because slowpoke wood haulers got caught in an ambush and jittery wrecks went to bury them. I'd love to be able to assign strong, fast dwarves to haul stone, the emotionally stunted to burial, etc. And further restrict the numbers of each type of hauler.

Convenience I guess. Roles are automatically matched with labors based on skills. But this does not work with unskilled labors. I don't think there is a default role for haulers (maybe it should be added to the TODO list in #88).

And you may want to enable hauling jobs for all dwarves that are not occupied. You will haul more with an army of slow dwarves than with a single fast one. No reason to waste the workforce.

There could still be a (optionally customizable) list of jobs for under-occupied dwarves, while having the possibility to add specific unskilled labors in the list to optimize. I don't think this would create any issue, but you will have to manually select a role for each unskilled labor.

qdbp commented 5 years ago

GLPK or CBC or Gurobi -- my proposal would be to leave the original algorithm intact and run the MILP solver via external executable only if the user has it installed. DT itself will just write an .lp file from the dwarf labor matrix which is probably annoying but can be done with no dependencies, and also to read the result. I have a strong mind to work on this, actually, because I crave optimality.

As for the haulers, it depends on playstyle. I like having specialists in all things. For outdoor hauling (wood/item/animal) and burial specifically I would like to have fixed-size role-optimized cadres rather than a grab-bag. Some hauling jobs are just more dangerous.