OrderedSet86 / gtnh-flow

Factory Optimization Flowcharts for Gregtech: New Horizons
MIT License
84 stars 24 forks source link

New Solver Failures #7

Closed OrderedSet86 closed 1 year ago

OrderedSet86 commented 1 year ago

New solver is desirable in terms of accuracy, maintainability, and speed, but has many regressions compared to the old solver. Here I track failures for fixing issues with the solver.

It is not entirely clear this problem can be solved as a linear program at all - might have to use some more arcane methods. Or maybe there is a bug in the DAG code. Or maybe the edge algorithm is vulnerable to lack of precision (for eg. recycling), which may cause issues with float math. It also fails on issues of max multiplier that the previous algorithm still solved (even if it was incorrect sometimes).

(I ignored renewables - there are too many files there to check.)

EmptySet failures:

circuits/lapotron_optimization
pe/apple
power/benzene/iv (after switching to mixed charcoal/distil benzene input to XLGT - this should be something new solver is in theory good at)
power/benzene/mv
power/benzene/nitrobenzene (if charcoal is mixed like the others)
power/hog/benzene (prob for same reason)
power/naqfuel/*
power/offmeta/sugar (when I add sugarbeet source)
power/oil/diesel
power/rocketfuel/* (if I do single ammonia source)
random/barley_power
random/beesuperfuel
random/jet_fuel
random/metal_mixture_gtpp
random/platline_test
2200_platline

Nonsense results:

testProjects/undeterminedMultiInput (This graph should be impossible to calculate due to ammonia for the LCR being undetermined)

Worked with nonlinear solve:

random/monazite_rare_earth
random/split_out_test

Broken for now due to power line changes:

random/ucfe_chemplant

Graph failed to generate due to syntax error:

random/burn_wood
OrderedSet86 commented 1 year ago

Looking at power/benzene/mv, it looks like there's an issue with the equation generator: image mv

OrderedSet86 commented 1 year ago

Solution - requires generating new variables (image should say 8 variables) image

OrderedSet86 commented 1 year ago

Implemented in https://github.com/OrderedSet86/gtnh-flow/commit/2499b0296d5db4e4831fab22534145c99861ee2a !!

Remaining issues: EmptySet result:

pe/apple
power/hog/benzene
power/naqfuel/* (light and heavy naq are not produced at the same ratios as they are consumed, so some would need to go to sink)
random/barley_power
random/jet_fuel

IndexError on variables from an arrayIndex call:

random/metal_mixture_gtpp

Correctly fails, but with unhelpful error message:

testProjects/undeterminedMultiInput (This graph should be impossible to calculate due to ammonia for the LCR being undetermined)

Broken for now due to power line changes:

random/ucfe_chemplant

Graph failed to generate due to graphviz syntax error:

random/burn_wood
OrderedSet86 commented 1 year ago

I know what's causing the remaining EmptySet errors, but I'm not sure how to write a general solution for it. It is specifically when a scenario like this happens (shown pre-locking, so no quantities): image

The relevant machines are:

- m: fusion reactor
  tier: LuV
  start: 1
  mk: 1
  I:
    heavy naquadah fuel: 30
    light naquadah fuel: 65
  O:
    naquadah fuel mk1: 100
  eut: 26000
  dur: 0.25
  target:
    naquadah fuel mk1: 10
- m: distillation tower
  tier: EV
  I:
    naquadah solution: 20
  O:
    naquadah asphalt: 2
    heavy naquadah fuel: 5
    light naquadah fuel: 10
    water: 10
    naquadah gas: 60
  eut: 1920
  dur: 1

The distillation tower produces light:heavy in a 1:2 ratio, but the fusion reactor consumes them in a 6:13 ratio. This leads to ambiguity as to what the multiplier for the distillation tower should be - is it 6:12 to provide the right amount of light, or 6.5:13 to provide the right amount of heavy? Obviously a human would pick 6.5:13 and simply sink the remaining 0.5 light naq fuel, but there is no equation in the system of equations representing "ok, you can send some to sink if there are no other alternatives."

I cannot simply detect single-step multi output to a machine, since the other failures have more steps before reaching the ratio mismatch issue. For example, random/barley_power (pre chem rebalance I think) has a DT producing ethanol:methane in 1:4 ratio.

The ethanol is 1:6 with bio diesel. The methane is 1:3 with hydrogen, hydrogen is 3:1 with ammonia, ammonia is 1:1 with nitric acid, and nitric acid is 8:2 with tetranitromethane.

This means the natural ratio for the DT is 6:1 bio diesel:tetranitromethane. But the cetane LCR consumes them in a 25:1 ratio. So I would need to have additional sources for the tetranitromethane from somewhere, or sink the excess bio diesel.

I could add source/sink edges to every machine, then try to solve the problem as a linear program which minimizes I/O from source/sink. But this sounds very technically difficult to program and prone to issues.

I could try and solve subgraphs until I find the one that's causing the issue, and then the partially complete graph can be shown to the user. But this also sounds very difficult, would take a week+ to implement at least.

I could try and have some way of finding this issue by inspecting the equations, and then it could be shown to the end user for them to fix. Or I could directly add a source/sink for the problem, although it's not always obvious what the "right" choice is to make automatically. (Above the right choice would be to produce more tetranitromethane - it's pretty cheap, and sinking bio diesel would be a waste.)

OrderedSet86 commented 1 year ago

This https://github.com/OrderedSet86/gtnh-flow/commit/0f599c0eddb8303625373b48c5941fd88793bf8c now notifies when an issue like this is detected and gives advice on how to fix it. Unfortunately this is still a lot of legwork for the end user. The solution can be automated, but it will take effort.

OrderedSet86 commented 1 year ago

Closing this because I'm switching to a new solver method for gtnh-flow 2.0, probably something involving PuLP (https://pypi.org/project/PuLP/) and explicitly modeling some stuff as a linear program. In particular this from earlier:

I could add source/sink edges to every machine, then try to solve the problem as a linear program which minimizes I/O from source/sink.