Tutorial:Prime splitter arrays

This tutorial is an essay from a personal perspective that serves as a guide to the creation of "prime splitter arrays"; collections of splitters and mergers that split resources by precise prime fractions. This is not possible for prime fractions above three using standard methods, but the application of some light mathematics can allow for players to precisely split resource lines into any desired fraction, which is highly useful when creating 100% efficient factory tree structures.

Introduction
Hello! While trying to make my factory designs as efficient as possible, I put a fair bit of work into designing "splitter arrays" in order to split resource lines in precise fractions for feeding my machines. Along the way, I stumbled into the "prime splitter" problem; the difficulty of splitting resources by fractions that cannot be expressed as multiples of 1/2 or 1/3 alone. For instance, say you have a belt of 100 iron plates per minute, and need to feed this into five assemblers that each take 20 iron plates per minute. Most players will do this using a "manifold" system, where the belt splits unevenly along the row of machines, and the first machine fills up first. This usually works fine, but also results in some latency in the system. In order for the system to start operating at 100% efficiency (and satisfaction) right away, you'd want to set up a "tree" system where the belts' resources are divided evenly into fifths. But how can this be done, when five isn't directly divisible by two or three, the only two possible splits that can be made in Satisfactory? Well, this is how! Read on.

I don't know if somebody else has done a tutorial on this. I've seen a few designs for 5x splitters et al, but in my experimentation I've identified a method based in a mathematical formula that allows one to split a resource line evenly into any prime fraction. This allows for easy 1/5th, 1/7th, 1/11th and 1/13th splits, and in fact should work for any and all prime fractions progressing to infinity. In practice, you probably won't want anything more granular than a 1/13th splitter (which is the smallest prime fraction that I've used in my builds in practice), but who knows!

I'll explain a bit of the theory of how and why this works, but if you just want a quick splitter design, scroll down for screenshots. Also, I'm no mathematician, and I've never really studied the subject beyond sixth form level, so my explanations and terminology may be lacking in that regard. But hey, this is a video game wiki and not a math journal after all!

Stating the Problem
A prime number, as most of you probably know, is a number that can only be divisible by one or itself. When it comes to dividing larger numbers down, prime numbers therefore serve as a sort of "building block" of large numbers, and are the smallest numbers that a larger number can be broken down into by repeated division, before you have to start dividing numbers by themselves. This process is usually referred to as "prime factor decomposition", and if you're anything like me, you did it in school by producing "prime factor trees" and reducing numbers to their prime factors by repeated division.

Relating this back to Satisfactory, the implication of this is that if you want to split a resource line by a certain ratio, you ultimately have to do this by repeatedly dividing the initial input by various prime numbers. Say you want to split a resource line by 1/28th. When building a splitter array to do this, you can't just immediately split by 1/28th; instead you have to split it into different subdivisions. You might first split the line by 1/7th, and then by 1/4th. The 1/4th can be broken down further into two 1/2 splits, and so in reality you are doing two 1/2 splits, and one 1/7th split. This is true no matter what order you do the splits in. This can be related back to the prime factor concept; the prime factors of 28 are 2, 2, and 7. So, essentially, in order to do any even resource split, you need to divide the input resource by all of its prime factors.

This is simple enough when a number has prime factors of only two or three, as Satisfactory's conveyor splitters have the ability to do 1/2 and 1/3 splits inbuilt (as they have three outputs). For instance, to do a 1/12th split, you can divide the line by 1/3rd, then in half twice, as twelve's prime factors are 2, 2 and 3.

But what about the example before, where the value you want to divide by has a prime factor greater than three? For instance, the prime factors of 10 are 2 and 5, and so to divide evenly by ten you'd need to split by 1/5th, which you can't do directly. So how can you ever split resources by these higher prime fractions. The answer lies in iterative sequences.

The Solution
An iterative sequence is a sequence defined by a formula where the output of the formula is also an input value for the next iteration of the formula. This should be familiar from math class if you ever worked with the formula for the "nth term". A simple iterative sequence could be defined by the formula "x(n) = x(n-1) + 1", where x is a number in the sequence and n is its position in the list. In this case, we are saying, "the nth number in the sequence has the value of the previous value in the sequence, plus one". So this sequence would increment in ones, "1, 2, 3..." etc. to infinity.

While this sequence will continue on forever, some other sequences have properties called "limits". These are "convergent sequences", and they will gradually get closer and closer to a "limit" with each iteration. For instance, a sequence where you divide by two every time will get infinitely smaller as you progress, towards an ultimate limit of zero. Although you would never get to exactly zero, you would eventually get close enough that you would be hard pressed to tell the difference.

Sequences can also converge towards other limits, including particular fractions. This property allows us to perform a little bit of magic and make splitter arrays that feed back into themselves so that the resource flow converges towards the limit that we want, even if we can not split to get that fraction division directly. Furthermore, these splitter arrays can be readily designed, because there is in fact a mathematical formula that will define an iterative sequence that will converge towards any prime fraction, which is as follows:


 * xn+1 = 1/(p+1) + xn/(p+1)

Where x is a number in the iterative sequence, n is its position, and p is the prime number we are attempting to divide by in the first place. This can be simplified to "xn+1 = (1 + xn)/(p+1)" if you want, but the above format is more useful for building splitter arrays. You now can clearly see that every iteration takes the fraction 1/(p+1) of the input resource rate and the same fraction of the feedback split.

One way that you can test whether or not this works is by replacing x with 1/p. As this represents the formula feeding itself its own limit, the result x(n+1) should also equal 1/p.

As for why the above formula works? If we look at the first few terms of this series we can find a pattern emerge (most of the arithmetic is skipped here as it is not complicated but would take a lot of space. Feel free to try it for yourself!):

x(0) = 1/(p+1)

x(1) = 1/(p+1) + 1/(p+1)2

x(2) = 1/(p+1) + 1/(p+1)2 + 1/(p+1)3

x(3) = 1/(p+1) + 1/(p+1)2 + 1/(p+1)3 + 1/(p+1)4

We are adding a successive power of 1/(p+1) to each term in the series. This has a very useful consequence. It means each successive term in the series has a constant ratio of 1/(p+1) from one term to the next (or in other words, you can factor out 1/(p+1) from each term.) This kind of series is well understood in mathematics and is called a geometric series and there is a formula for finding the value a geometric series converges to! First we have to define a couple things, the value a which represents the first term in the series and the value r which is the ratio between terms in the terms in the series. So in our case

a = 1/(p+1)

r = 1/(p+1)

The formula only works if |r| < 1. In our case |1/p+1| 0. Integers greater than 0 are all we interested in since you can't have a negative number of splits anyway so we are safe to use the formula which will show us what the series converges to.

Σ ark = a / (1 - r)

= (1 / (p + 1)) / (1 - 1 / (p + 1)) substitute our values

= (1 / (p + 1)) / (p / p+1))         get a common denominator and simplify

= 1/p                                        cancel terms

And there you have it. The above series converges to 1/p for all p greater than 0.

The upshot of this, however, is that you can create a sequence that tends towards a given prime fraction as its limit by dividing an input line by the whole number one above the prime fraction that you are trying to divide by, and then feeding the output of your splitter array back into the start of itself. This will always be possible, as, because all prime numbers are odd, the number above them will be even. Therefore you can always have the last splitter in the array be a 1/2 splitter, and have one output as the fractional output, and the other output feeding back into the start of the splitter.

This will split the incoming resources into one output that is a separated "1/pth" of your incoming resources, where p is the prime number you are trying to divide from. For instance, if you are dividing by 5, your main output will be 1/5th of the incoming resources. You can then collect the rest of the split outputs in mergers, creating a second output with the remaining 4/5ths (or, more generally, p-1/pths). This can then be further split if you want a truly even 1/5th division into five separate outputs, by using a standard tree of 1/2 splits. Sometimes you may need an additional prime splitter to do further splits, but as the output fraction of p-1/p must always be divisible by two (as p is always an odd number), then you will always be able to get smaller, until eventually you have something that can be split evenly using normal 1/2 or 1/3rd splits!

Sorry if all that was a bit obtuse. Here's some examples of how to actually build the things!

Alternative explanation

It may be confusing to think of splitters/mergers as performing division/addition. After all, math in Satisfactory is discrete - you can't divide screws into two. We can think of them as finite state machines instead. Splitters and mergers have 1-3 states, depending on how they're hooked up - the state determines which output the input is sent to for spitters, or which input is taken for mergers. They're also deterministic - the states always advance in the same order, and a given input always results in the same output.

With that in mind, let's look at the 1/5th splitter:

> M2 > 4/5ths ^  ^ 1/5th < S2 < S1 < M1 < 1 \/     ^          > > >

Based on the splitters, there are 6 total states in this machine. Let's see what happens to the first six elements passed through. We assume that the splitters output in sequence counterclockwise.

1. M1 -> S1 -> M2 -> 4/5ths 2. M1 -> S1 -> S2 -> M2 -> 4/5ths 3. M1 -> S1 -> M2 -> 4/5ths 4. M1 -> S1 -> S2 -> 1/5th 5. M1 -> S1 -> M2 -> 4/5ths

We enter the loop on the 6th item: 6. M1 -> S1 -> S2 -> M1 (loop!)

To summarize, S1 and S2 combine to distribute five items, and send the sixth back to the source. Now we take the next five items, distribute them, and throw the sixth back again... and so on to infinity. But this doesn't actually improve efficiency at all - all the work spent to move item 6 through the loop was wasted! Assuming that the input is sufficient to fill the pipeline, we'd be better off just throwing item 6 away - when it arrives back at M1, it'll just block one of the fresh inputs that would've otherwise gone in.

It's a fun math exercise, though.

Illustrated examples
In these examples I will primarily be showing you prime fraction "separator" arrays, rather than full even prime splitters. This is the most difficult part of the splitter array to construct, as it is the part that does all the actual iterative feedback stuff. Usually, you can simple tack a standard even tree splitter to the larger of the two outputs to break it down into a fully even split in p directions.

1/5th Splitter


The layout is as such:


 * S = Splitter
 * M = Merger
 * Arrow = Belt direction
 * 1 = initial input
 * Fraction = Output fraction

> M > 4/5ths ^  ^ 1/5th < S < S < M < 1 \/     ^          > > > This is my design for the simplest prime splitter, the 1/5th splitter. The input comes from the crate on the far right, and the 1/5th output is the crate on the left. The crate at the top-right catches the other 4/5ths of output. So, if you put 50 iron plates in the crate on the right, you will end up with 10 plates in the left crate, and 40 in the top crate. Keep in mind that these resources may not all be allocated instantly; the nature of the recursion is that the system requires a few "iterations" in order to sort the goods, and so things may cycle around the machine multiple times before ending up in the correct place. In all my tests, however, they have ended up being evenly split eventually, even with large amounts of goods.

You can see here how, as I explained above, the array is actually splitting the input into two sixths (p + 1 where p = 5), and outputting one while feeding the other back into the start.

It is worth saying that this design differs from my standard design pattern because the final splitter here actually splits three ways, as opposed to the final two-way splitter that I mentioned above. The 1/2 final splitter is good because it always works, but in this case placing a 1/3rd splitter last does work, and is possibly preferable as placing it in the middle means looping belts over the top of the machine.

1/7th Splitter


The layout is as such: > M > 6/7ths ^  ^ 1/7th < S < S < S < M < 1 \/         ^          > > > > > The 1/7th splitter looks very similar to the 1/5th, except with an extra splitter, to bump up the amount of initial pre-feedback splitting from 1/6th to 1/8th. This time, I actually do put a 1/2 splitter last, as usual. The input and output crates are the same as before; putting 49 plates in the rightmost crate will result in 7 in the crate on the left and 42 in the crate on the top (1/7th and 6/7ths).

1/11th Splitter


The layout is as such: > M > M > 10/11ths ^  ^   ^ 1/11th < S < S < S < M < 1 v          ^ > > > > > This 1/11th splitter design is essentially the same as a 1/7th splitter, with the addition of an extra belt and merger in the top left, to get the pre-feedback split to a 1/12th. For similar reasons as with the 1/5th, I have put a 1/3rd splitter as the final splitter instead of a 1/2 in order to avoid having to loop a belt over the top.

One thing to note about the 1/11th split is that the collected output in the top right, the 10/11ths, would need to be fed into its own 1/5th splitter in order to divide this output by 10 in order to get 11 even outputs.

1/13th Splitter


The layout is as such: > M > 12/13ths ^  ^ 1/13th < S < S < S < S < M < M < 1 \/ \/          ^   ^         \/    > > > > >     ^           > > > > > > > > >   The most complicated splitter design I'll be showing here today is this 1/13th splitter. Again, the input and output crates are the same. If you look closely, you will be able to see that the layout above is in fact just another 1/7th splitter, surrounded by another splitter/merger pair feeding back across into each other. This is because in this case p + 1 is 14, and so we have to divide the initial input by 14; first by using a 1/7th splitter, and the by putting our usual 1/2 splitter at the end. This method of nesting prime splitter arrays is useful if you have a value of p + 1 that doesn't factorize immediately to twos and threes.

The layout is as such: > M > 12/13ths ^  ^ 1/13th < S < S < S < S < M  < 1 \/ \/          ^           > M > > > > > ^

You can create a 1/13 by first dividing it into 16 pieces and then putting 3 of them back into the output. This is a simple method, but the throughput is worse.

1/5th Splitter with full five 1/5th outputs


For the purpose of demonstration only, here I've hooked up the same 1/5th splitter design as above to an additional 1/4 splitter tree in order to get give even 1/5th outputs, as in the situation given at the start of this tutorial. As you can see, the 1/5th splitter works as normal, and then the remaining 4/5ths is split in two, then each of the 2/5th outputs is split in two again, resulting in five perfectly even 1/5th outputs.

Construct, combine, conquer!
And there you are! The illustrated examples shown here are only the basic building blocks for what can be far more complicated combined splitter arrays. For fraction splits that are multiples of a prime fraction, for cases when a greater throughput is needed (see notes below), or just for any complicated multi-stage splitter-merger operation you can dream up, the basic prime splitter array designs can be combined, restructured, and reshaped to fit your needs.

As an example for how more complex builds can develop, here is an image of one of my own factory balancers, employing six separate 1/5th splitters stemming from two input belts and branching from each in thirds, then recombining individual belts as required to feed the desired resource fractions into an oil refinery array.

Additional notes
As stated above, because these splitter arrays have to recursively feed into themselves a few times in order to work out the balance correctly, they will not split instantly. The larger the array, the longer you'll have a few resources shuffling around inside before they are output into the correct crate. If you are constantly feeding a supply of resources, however, you should be able to expect the system to even out to a constant output of the correct fraction from each output.

With respect to throughput: possibly because of the recursive loops feeding back into themselves, these splitters have a tendency to back up before reaching the full items/minute limit of the belts you use. This can result in items not passing through the splitter array fast enough. For instance, the above splitters would likely back up due to internal bottlenecks if you fed them the full 480 resources per minute, despite the across board use of Mk. 4 belts. Due to this, for exceptionally high throughputs it is worth splitting your resources evenly into multiple different splitting arrays, so as to reduce the load on each individual array, and then merging the outputs back together afterwards to avoid having resources backing up and getting stuck!

Another note about maximum load: Since the 1/p splitter feeds back 1/(p+1) items into the input, the maximum throughput or the splitter is limited to p/(p+1) of the input belts maximum speed (assuming you don't mix belts). As an example, the 1/7 spitter feeds back 1/8 of the items, and the maximum throughput is limited to 7/8 of belt capacity (e.g. 420 items/min for Mk.4, 682.5 for Mk.5).

For nested spitters, such as the 1/13 spitter, care has to be taken to not compound these bottlenecks. However, it is possible to design them in such a way that the optimal throughput of p/(p+1) can be achieved. Putting the 1/2 splitter that every design contains right after the merger and before any nested splitters is the easiest solution.

If you start every splitter array with a splitter first then you can guarantee the lines coming out of that first splitter are not saturated at the maximum throughput of the original input belt. Then when looping back the 1/p+1 line, split it first with a single splitter and merge it back into the resultant non saturated lines from the output of that original splitter. Doing it this way will require a little more complexity, (at a minimum 1 extra splitter and 2 mergers extra) but it will allow your prime splitter to consume its input line at the full throughput of that line making each output a true 1/p even split of that input.