Representing manufacturing pipeline in game Dyson Sphere (Factorio clone) as a linear programming problem

107 Views Asked by At

I'm looking to express the following problem from the game Dyson Sphere in terms of linear programming.

I can build a circuit factory which produces 45 circuits per minute. Each circuit requires two iron_ingots and one copper_ingot. I can build iron_ingot factories each of which produce 60 iron ingots per minute. The iron_ingot factory requires one iron. I have an iron factory which produces 180 iron per minute. I can build copper_ingot factories each of which produces 60 copper_ingots per minute. Each copper_ingot requires one copper. I have a copper factory which produces 150 copper per minute. Use linear programming to maximize circuit output.

Basically I'm trying to figure out how to build, to the nearest whole number, the optimal number of factories at each stage of the pipeline to produce at least 45 circuit boards / minute.

I have written the following code that calculates the number of copper_ingot and iron_ingot factories that I should build:

from scipy.optimize import linprog

c = [-60, -60]
A = [[60, 0], [0, 60]]
b = [150, 180]
copper_bounds = (0, None)
iron_bounds = (0, None)

res = linprog(c, A_ub=A, b_ub=b, bounds=[copper_bounds, iron_bounds], method='highs')

print(res)

Where I am stuck though is trying to figure out how to bring the circuit into the mix conceptually.

In the augmented form I have (so far):

$[[60, 0, 0, 150],[0, 60, 0, 180],[0, 0, 45, ?]$

where column 3 is circuits but I don't see mathematically how to tie the circuits back to the amount of copper and iron ingots.

Edit

Shower thoughts: - I feel like the '?' must be something like $60x_1+60x_2$ but that's not quite right. The fact that it couldn't be higher than the total output of the copper_ingots and iron_ingots has to be in there though

Answer

My corrected code after wrapping my head around things is:

from scipy.optimize import linprog

c = [-2, 0, -1, 0]
A = [[1, -60, 0, 0], [0, 0, 1, -60], [0, 0, 1, 0], [1, 0, 0, 0]]
b = [0, 0, 150, 180]
copper_bounds = (0, None)
iron_bounds = (0, None)

res = linprog(c, A_ub=A, b_ub=b, method='highs')

print(res)

and that outputs:

C:\Users\grant\Documents\code\math\venv\Scripts\python.exe C:\Users\grant\Documents\code\math\dyson_sphere\circuit.py 
        message: Optimization terminated successfully. (HiGHS Status 7: Optimal)
        success: True
         status: 0
            fun: -510.0
              x: [ 1.800e+02  3.000e+00  1.500e+02  2.500e+00]
            nit: 0
          lower:  residual: [ 1.800e+02  3.000e+00  1.500e+02  2.500e+00]
                 marginals: [ 0.000e+00  0.000e+00  0.000e+00  0.000e+00]
          upper:  residual: [       inf        inf        inf        inf]
                 marginals: [ 0.000e+00  0.000e+00  0.000e+00  0.000e+00]
          eqlin:  residual: []
                 marginals: []
        ineqlin:  residual: [ 0.000e+00  0.000e+00  0.000e+00  0.000e+00]
                 marginals: [-0.000e+00 -0.000e+00 -1.000e+00 -2.000e+00]
 mip_node_count: 0
 mip_dual_bound: 0.0
        mip_gap: 0.0

Process finished with exit code 0
1

There are 1 best solutions below

0
On BEST ANSWER

$ x_i \le 60x_{if}$
$ x_c \le 60x_{cf}$
$ x_i \le 180$
$ x_c \le 150$
$ 45 \le 2x_i + x_c$
Max $ 2x_i + x_c$
Or simpler
$ x_{if} \le {180\over60}$
$ x_{cf} \le {150\over60}$
Max $ 2(60)x_{if}+60x_{cf}$