1
$\begingroup$

With the rise of factory games like Satisfactory and Factorio, many people have started wondering about problems like these.

Factorio already has a very interesting analysis of conveyor dynamics on this question: Belt Balancer problem (Factorio)

As so I will be focusing on a particular problem that shows up in the game Satisfactory.

The key ideia is:

Having a conveyor belt with a known flow of items per second, how to split it into multiple belts, possibly with different flow rates?

On Satisfactory the allowed operations are:

  1. Splitting a belt in 2 -> 2 new belts, each with 1/2 the flow rate
  2. Splitting a belt in 3 -> 3 new belts, each with 1/3 the flow rate
  3. Merging several belts into one.

This set of rules allows for a split belt to be merged into the source stream of the splitter, creating feedback loops that converge into a specific distribution, as shown here. This graphic was brought to my attention on a similar question, trying to solve a particular case of this problem: How do I get 1/15 of something, only by divide with 2 or 3 and add the result back together?

This youtube video also shows solutions for several particular cases of this problem.

While my math skills aren't very good, my ambition certainly is. I would like to see a general solution for this problem, and turn into into a calculator program (because my programming is better than my math).

The objectives of this question are:

  1. Obtain a proof that it is possible to take one input conveyor with any flow rate and turn it into any number of output conveyors, with any flow rates (outputs can have different flow rates). Or figure out which combinations are impossible.
  2. Create a general solution / algorithm to solve this problem:
    • Given an initial flow rate $X$ which operations need to be applied so that a specified output can be achieved? The most general case would be to allow any number of conveyors, each with any possible flow rate. (Order of conveyors does not matter, we only need to specify how many with what flow rate)
    • To put in more "mathy" terms, the inputs to this would be:
      1. The input flow rate $X$
      2. A specification of how many conveyors are desired with which flow rate: $n_1$ conveyors with $F_1$ flow rate, $n_2$ conveyors with $F_2$ flow rate, all the way to the $n^{th}$ row $$ \left( \begin{matrix} n_1 & F_1 \\ n_2 & F_2 \\ ... & ...\\ n_n & F_n \end{matrix} \right) $$ This matrix can have any number of rows but $$n_1, ..., n_2 \in \mathbb{N}$$ As the left column values are counters for the number of output conveyors, and $$\sum_{i=1}^{n} n_i F_i = X$$ As the sum of all flow rates of all conveyors must equal que initial flow rate.

With this, the general solution should provide a way to figure out the tree of operations that need to be applied to the initial conveyor to achieve the end result, i.e.

+------------------------------------+---------------------------+
|             Operations             |         Conveyors         |
+------------------------------------+---------------------------+
| split initial in 3                 |  X/3 |  X/3 |  X/3        |
| split one of the 10/3 in 2         |  x/3 |  X/3 |  X/6 |  X/6 |
| merge one of the 10/6 with initial |  X/3 |  X/3 |  X/6        |
+------------------------------------+---------------------------+

It is my impression that the feedback and convergence complicate this quite a bit, and it would be best solved numerically, by coming up with a programmable algorithm and having the computer figure it out, finding convergence iteratively and proposing a solution.

Here I am only interested in the operations, leaving it up to the engineer to implement the system in-game, and that is why I have not specified conveyor flow rate limits or other limits related with the physical reality inside the game.

This is a problem that has boggled me for quite some time and I have put considerable effort in preparing this question. Even we never come to a perfect solution I would most certainly like to hear your thoughts and opinions on how to tackle this!

Also I'm not sure how to tag this question as I don't know which fields of mathematics this problem is related to - suggestions accepted.

$\endgroup$

3 Answers 3

1
$\begingroup$

If we take our initial flow rate and estimate it in N steps with "splitters", each having K>0 multiplier rate, then on n-th step maximum error can be estimated with (K^n)/2. Error converges to 0 for K<1 => numbers can be achieved as precisely as we want as long as they're smaller than input.

The rule for connecting output to input is that the rest of outputs keep their proportions but their sum is 1. You can divide by 15 by having 27 outputs each with 1/27 fr, 12 of which are connected to input. That occurs due to the fact that anything that enters conveyor must exit (fr>=1), nothing is stocated inside of it (fr<=1) and each exit has the same fr.

You can as well convert your number to base 3 (or any other base you can split with). For example, 1/15 would become 0.00121012101210121... That means your output will be 1*(1/3)^3+2*(1/3)^4+1*(1/3)^5 = 1/27+2/81+1/243+...

$\endgroup$
1
  • $\begingroup$ Sorry, I've read this many times and I feel like I don't really understand it. What is K and what is the Error you talk about on the first paragraph? The idea of the second paragraph is that if I take any integer N, to divide a stream into N equal conveyors, all it takes is to find the smallest multiple of 3 (or 2) above N (let's call it X) and feed X-N conveyors back into the input correct? If so this doesn't hit me like the optimal solution as a large number of splitters and mergers would be required. Ideas? $\endgroup$
    – rosaqq
    Nov 24, 2020 at 12:43
1
$\begingroup$

You can achieve any rational flow rate, or more generally any combination of flow rates. Because the flow rates can be written as a solution to a rational linear system of equations, irrational flow rates are not possible.

To achieve a specific flow rate, one solution is to leverage an algorithm for sampling discrete uniform distribution from a fair coin. Let me explain such an algorithm first, and then how to implement it with conveyors.

Suppose you are given a fair coin, and you want to randomly choose an integer between 1 and 5 with uniform probabilities. What you can do is toss your coin 3 times, then you have 8 possible outcomes. If you get one of the five first possible outcomes, you output the index of that outcome. Otherwise, toss the coin again. Each time you toss the coin, the number of possible outcomes doubles, so there is now $(8-5) \times 2 = 6$ outcomes. Again for the 5 first outcomes, output an integer, and otherwise toss again.

It is not hard to see that after $n$ tosses, there are $2^n \mod 5$ undecided outcomes. Also if we define $b_n$ to be $1$ if an integer may be generated after $n$ tosses, and $0$ otherwise, then $0.b_1b_2b_3\ldots$ is the binary representation of $1/5$. Because $1/5$ is rational, that representation is ultimately periodic. This means that after some number of steps, we loop back to a previous state. Hence we can encode the algorithm as a finite automaton. In our example, after tossing the coin $4$ times, we are back to only one undecided outcome, which is just like the initial condition. This algorithm minimizes the expected number of tosses, but this is not enough to get the automaton that minimizes the number of states (which would be more interesting to you), more work would be needed for that.

Let's go back to Satisfactory now. A 2-splitter is just like a toss of a fair coin: items are divided into the two output belts uniformly (from the viewpoint of individual items, this just looks like random choices). By implementing the automaton using one 2-splitter for each state, and merger when a loop back is needed, you get a network that splits your input into 5 belts uniformly.

There is nothing special about the value 5 chosen above, all this works for any integer. If you want a throughput $n/d$ you can easily split into $d$ outputs and then merge $n$ of them.

Notice that, in general, there will be cycles in the network. As a consequence, some belts may end up with a higher throughput than your input belt. It will never be much higher, so as an easy fix you can just split your input into two networks and merge their outputs.

There is still work to do to get an optimal solution in terms of number of mergers and splitters, in particular using 3-splitters too.

If you want to get a particular distribution, say for instance 20%, 31% and 49%, we use the same principle. Firstly, find the binary representations of the values in your distribution:

\begin{align} 0.20 &= 0.001100110011001...\\ 0.31 &= 0.010011110101111...\\ 0.49 &= 0.011111010111000... \end{align}

From this, build a binary tree. Reading the figures in the binary representations column by column, a "1" tells you to put on "output" for the given value at the depth equals to the column index. For instance, for the 20% output, there should be an "output" in depths 3,4,7,8 and so on.

The upper part of the infinite tree for distribution 20%, 31%, 49%

We get an infinite tree, but it is ultimately periodic, so at some point you will be able to add a loop back to a previous node. Because that tree may be quite big, you probably want to change the distribution by adding an explicit "loopback" output, that encode the fact that we can start again. This allows us to get a denominator that is a power of two, so the binary representations are finite.

\begin{align} 20/128 &= 0.00101\\ 31/128 &= 0.0011111\\ 49/128 &= 0.0110001\\ 28/128 &= 0.00111 \end{align}

From this, we get the tree below, where an "r" node means that we loop back to the root.

The finite tree for distribution 20/128,31/128,49/128,28/128

Again, we must be careful not to saturate the root node with the loopback, the easiest way is to duplicate the root node (merging the left (respectively right) outputs of the root and its duplicate).

$\endgroup$
2
  • $\begingroup$ I'm having a bit of trouble understanding the coin algorithm. If in the first 3 tosses I get an outcome other than the first 5, I toss again. So these remaining 3 outcomes become 6, meaning I can choose the first 5. But if the toss again lands on the 6th (undecided) outcome... do I restart and just throw the 3 coins again? In the satisfactory case I understand perfectly as I just have to merge back all the undecided outcomes to the source flow. However this solution leaves me with 5x 1/5 flows and I would have to reapply it several times to generate a 20% - 31% - 49% separation for example. $\endgroup$
    – rosaqq
    Jun 21, 2021 at 0:05
  • $\begingroup$ Restarting would be exactly the same as just going on, in the case of 1/5, because the period has length 4 in that case. I added a detailed explanation working with the distribution 20%-31%-49%. $\endgroup$
    – Guyslain
    Jun 22, 2021 at 7:19
-1
$\begingroup$

I believe your over complicating by the multiple belt speeds, essentially your limit is your current maximum belt. Example a tier 3 belts max capacity is 270. Any other inputs cannot exceed your proposed limit. At this point all your merging and splitting will follow based on this limit.

The belt tiers lower than your maximum will not matter at that point and you can use a switch to lower the belt speed based on the splits total output for example if (output <= 60) belt = beltTier1;

You will likely need a variable for the current max belt, a variable for starting input material value, and a variable for required manufacturer input value or split final values, as well as a variable for remainder that cannot be evenly split. You will want a class to represent the Splitter (divider) and Merger (adder) where it has a restricted divide by 2 or 3, and the adder that can only add up to 2 or 3 inputs.

for the merger you would also need to use the Max Belt as a restriction to prevent an attempt of adding more than the max.

This problem will likely need machine learning to calculate the optimal splits and merges to get the required inputs for the manufacturer.

$\endgroup$
1

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .