24
$\begingroup$

So this question is inspired by the following thread: https://forums.factorio.com/viewtopic.php?f=5&t=25008

In it, the poster is examining an $8$-belt balancer (more on that to come) which he shows fails to satisfy a desirable property, which he called universally throughput unlimited.

So what is a $n$-belt balancer? It is a configuration of belts (which move items around), and splitters (which take two belts in and balance their items on the two belts on the output side), which will balance the input of all $n$ input belts across all $n$ output belts. They are frequently used in large factories to move large amounts of items to a variety of different areas in a manner where no one belt worth of items getting backlogged (more items coming at it than it can use) results in other projects not getting full throughput (or at least as much as they can use).

The desired property called universally throughput unlimited is the following: Suppose only $k$ of the $n$ input belts are getting input (assume full input; aka, input belts are assumed saturated), and that all but $k$ of the output belts are backlogged and have no throughput (already full of items and nothing is moving on those belts). Then the full input on those $k$ input belts can be provided across the $k$ output belts (which have the same maximum throughput, hence no one output belt can handle more than one input belt's worth of throughput). This basically means that the $n$-belt balancer is never a bottleneck no matter the current input or output limitations (which lanes are getting input/available for output).

The question I have is the following: It always possible to create an $n$-belt balancer satisfying the universally throughput unlimited condition for any $n$? It not, for which $n$'s is it possible? (clearly, $n=2$ works because of how splitters behave)

I have some ideas on how to approach this problem, but am nowhere near having it solved. The first idea is about how to represent the problem: We can represent the input belts and output belts as vertices of a directed graph. The inputs being sources (in-degree=0) and the outputs being sinks (out-degree=0). The balancer is the input and output vertices together with a set of intermediate vertices which represent splitters which have $1\leq$in-degree,out-degree$\leq$2 (one or two directed edges point to them and one or two coming from them) and the associated directed edges. Looking at the problem this way, it is easy to see that a necessary condition is that input on any belt can reach any output belt (it is necessary because if not, then consider the case of all input on one input belt and all but one output belt backlogged with 0 throughput; in such a case, if you can't route that input belt's input to the output belt you won't get any throughput), but this condition is not sufficient (multiple examples that satisfy this condition have been shown both theoretically and experimentally to fail to have the desired universally throughput unlimited property).

An important thing to note is that belts can be routed under other belts via underground belts, hence planarity of the above described graph is not necessary. The fact that splitters have some very specific behaviors is important to this problem: They will always try to balance outputs provided there is no backlog, hence, in a no backlog scenario the output on each belt leaving a splitter is half of the total input on both of its input belts. If however, one of the output belts is backlogged with no throughput, then all of the throughput will be merged onto the 'free' belt up to it's throughput limit. If more than one belt worth of throughput is coming into a splitter in this case, then both input belts will start to bottleneck (each belt's effective throughput will be half of the maximum because that's how much of the saturated output belt is coming from the given input belt). Sometimes a backlog is only a reduction in throughput (do to bottlenecking down the line somewhere) in such a case, a splitter will still split input equally up to that the reduced throughput on the lowest throughput belt, after that, all remaining throughput is thrown at the belt with additional capacity until that two is saturated, and if there is any more input coming at the given splitter then both of its input belts will start to backlog.

This backlog phenomenon can result in some very subtle behaviors. Which makes simply assigning weights to the directed edges in the above described graph (constrained to a value of $[0,1]$ where $1$ is saturated and $0$ is no throughput) inadequate to describe the problem. For instance a splitter causing a backlog with some throughput but not enough to avoid backlog, can lead to a reduction in throughput for another splitter's output belt, shifting more of it's input onto the other output belt (which might cause a splitter further down that belt to suddenly become a bottleneck and backlog, etc.)

My suspicion from experimenting a tad as well as some theoretical work looking at how splitters are dividing inputs leads me to conjecture that it is not possible for all $n$, and that the most likely candidates are powers of $2$. Even then, for powers higher than $1$ it still might be impossible because of odd #s of belts having input needed to get to same number of output belts (and if balancing odd #s of belts isn't possible, then the universally throughput unlimited condition might not be satisfiable because of these cases).

$\endgroup$
  • $\begingroup$ This is nowhere near an answer, But I believe that if you have a balance of 'n' Belts, you can extend this for '2n' belts. (2 applications of the 'n' belt balance?) This could be extended to work for all multiples of n and hence work with 'kn' belts. This would mean you only need to make special balances for prime numbers (who have no simpler multiples) $\endgroup$ – Kieren Pearson Jul 13 '16 at 1:59
12
$\begingroup$

UTU = Universally throughput unlimited

There exist UTU balancers for 3, 4, and 5 belts, and likely for any number of belts. Examples are given in this Jupyter notebook, along with a Python implementation of an iterative algorithm for computing the flow for any set of belts and splitters.

I will quote some of the notebook here for those who don't wish to follow the link. I refer to splitters as junctions, since that's how they really function.

Each belt is composed of unit length segments, referred to in the game as tiles. In the model, we imagine each belt flowing from left to right along coordinate direction $x$ and each junction uniting two belts at the left edge of a given tile. Note that some balancers used in practice contain loops and could not be represented by our model without an infinite length belt.

The state of a belt tile is represented by a density $0 \le \rho \le 1$ and a velocity $0 \le v \le 1$. The value $v=1$ is the normal belt speed, and $\rho=1$ is the maximum capacity of a belt. Clearly, we can only have $v<1$ if $\rho=1$; this is a state in which the belt is fully loaded and there is not enough outflow downstream.

The inflow upstream is specified by the density $\rho_{up}$ at the left edge of the domain ($x=0$) and the outflow downstream is specified by $v_{down}$ at the right edge of the domain. For the purposes of testing UTU, we are only interested in setting these values to zero or one, but more general values will work with the algorithm below.

The main condition to be satisfied is conservation at each junction. The flux of items along a belt is given by the product $\rho v$, and we require that the flux going into a junction be equal to the flux coming out. It turns out to be much more complicated than I expected to satisfy this condition at each junction in a way consistent with how splitters work, and that is reflected in the code below. When I have time, I will hopefully add a more precise mathematical description of the conditions that are applied in the algorithm in order to achieve conservation.

Briefly: we initially set $\rho=0$ and $v=1$ everywhere except at the boundaries. At each iteration, we only increase $\rho$ and decrease $v$; the iterative values are always lower (respectively upper) bounds on the correct values. At each iteration, we check for junctions where inflow is greater than outflow (due to the conditions in the previous sentence, the opposite situation cannot happen) and adjust them in order to achieve conservation and equal outflow. If possible, outflow densities are increased to achieve this. If that's not possible (because one of the outflow densities reaches 1) then all excess outflow is assigned to the other belt. If that's not possible (because both outflow densities reach 1) then one or both of the inflow belts will fill up and slow down.

Here is a simplified view of one flow through a UTU 3-belt balancer: 3-belt UTU balancer The numbers are densities and the colors are velocities. Again, flow is left to right, and each black line represents a junction ("splitter"). Here's what it looks like in the game:

3-belt UTU in game

This seems pretty simple and obvious; I'm surprised that it hasn't been posted in the Factorio forums already.

Here's a 4-belt UTU balancer:

4-belt UTU

and one way to construct it in-game:

enter image description here

I think this has already been invented and posted on the Factorio forums, although I came to it independently.

The notebook has a 5-belt balancer too, but I haven't taken the time to build it in-game.

The notebook includes code to generate and test all the required sets of inputs and outputs for the UTU property.

You'll notice that these balancers are built by naively putting as many junctions in as one can fit, and staggering them. I conjecture that if you do enough of this, you'll always get a UTU balancer, but I have no idea how the length of the balancer grows with the number of belts. Interestingly, my 4-belt balancer is shorter (in the model representation, where belts can be combined willy-nilly without worrying about the actual geometry) than the 3-belt balancer. But the 5-belt balancer is much longer.

The algorithm in the notebook could also be used to investigate other scenarios, such as $m$-to-$n$ balancers with $m$ not equal to $n$, or to test the idea put forward in other answers that a $2n$ UTU balancer can be built up from an $n$ UTU balancer. It would be straightforward to attach it to some brute-force or more intelligent search that tries to find the shortest possible balancer with some given properties.

I must say that I am surprised by the complexity of this problem, which I initially thought would be much easier to solve. In particular, I haven't yet been able to come up with an explicit approach to the solution, only the iterative algorithm in the notebook. Thanks for the very interesting problem.

Update: In the comments it is claimed that the 3-belt balancer fails if the top input and bottom output are disabled. Here is the picture for that situation, showing full throughput:

enter image description here

Notice that the splitters are doing exactly what @Rhamphoryncus claims they should. For instance, the splitter connecting the lower two belts on tile 2 (the third tile) pulls exactly 1/2 of a full belt from each of the two upstream belts. The same happens with the splitter joining those two belts on tile 4.

$\endgroup$
  • 1
    $\begingroup$ You clearly put a lot of work into this, and I think you have a nearly complete solution for iteratively constructing UTU balancers. I say nearly complete because there is one thing you didn't account for that can actually matter in practice, and this is the individual lanes on the belts (admittedly, this was not part of the question I originally posed here). The more recent posts in that thread demonstrate why lanes can matter, and in practice, I have gotten the classic 4-4 balancer to fail UTU because of resonance patterns established during underloaded conditions that carried into full. $\endgroup$ – Justin Benfield Oct 3 '16 at 10:06
  • 1
    $\begingroup$ The big issue is that belts have two lanes, and splitters never change an item's lane (e.g. if it was in left lane, it stays in left lane, even if it's moved to the other belt), which makes the situation slightly more complicated. Moreover, splitters also have a 'memory' for each item type of where the last 5 items were output to (left belt or right belt), and try to keep left/right balanced. This means that a splitter that's been forced to output on one belt only for a while will suddenly output only on the other for a bit before returning to the 'back-and-forth' pattern you'd expect. $\endgroup$ – Justin Benfield Oct 12 '16 at 7:38
  • $\begingroup$ The 3-belt fails if the top input and bottom output are disabled. The 4-belt fails if any 1 input and output are disabled. I believe your model is backwards - once a splitter is backlogged it also balances which input it pulls from, so inputs with 1.0 and 0.5 actually get 0.5 pulled from each. $\endgroup$ – Rhamphoryncus Oct 21 '16 at 21:30
  • $\begingroup$ @Rhamphoryncus I've addressed your claims in an update at the bottom of the post. $\endgroup$ – David Ketcheson Oct 22 '16 at 3:58
  • 2
    $\begingroup$ Of course, a problem of that 3 balancer is that unless the inputs are saturated, it will not actually output to all 3 output belts equally. A 4 Balancer with its one of output lines looping back to the input would however. $\endgroup$ – Tally May 8 '17 at 12:03
3
$\begingroup$

This is not a complete answer but

Assumption 1: a unlimited 4:4 balancer is possible. My belief is that this is throughput unlimited.

Take the design of the 4:4 balancer, replace each 2:2 balancer with a 4:4 balancer and you should have a 8:8 balancer which I believe to be unlimited

A bit more general: If we have an n:n balancer, where n is some power of 2, we can get 2n:2n by taking the design of the 4:4 balancer and replacing each 2:2 balancer with a n:n balancer.

This assumes that it is always geometrically possible.

By induction all powers of 2 should have throughput unlimited balancers.

Addendum 1: Assuming that the above holds then as throughput unlimited balancers are possible for powers of 2 a throughput unlimited balancer for a smaller number can be achieved by blocking of the extra inputs/outputs.

Addendum 2: (This is just pure speculation) If we have a set of belts in a certain order all heading in the same direction we should be able to switch place of any 2 belts in the order by having all other belts use underground belts for a few squares. Thus we can permute belts arbitrarily as any permutation of 2 belts is possible. This should mean that we can always build 2n:2n balancers from n:n ones.

$\endgroup$
2
$\begingroup$

This isn't quite a math-y answer, but it sounds like you're reinventing the nonblocking minimal spanning switch and Clos networks. In this case, a splitter is essentially a 2x2 crossbar switch, and you're using them to build bigger switches.

As a simple example if you have a NxN switch (in this case, a 2x2 splitter), you can use 3N of them (3*2=6) to build a switch that is N2xN2 (and thus, the popular 4x4 balancer design that uses 6 splitters).

If you wanted a 16x16, you could then take 12 of those 4x4 balancers, have 4 on the input side, 4 on the output side, and 4 in the middle, with every switch connected to every switch in the next stage with one belt. You could then repeat this process to get a 256x256, etc.

After that, I'm not entirely sure about the math, but I think you'd be able to, eg, cut a design in half to get half the throughput (eg, 6x 4x4 balancers to get a 8x8). You could then get things that aren't powers of 2 by just not connecting some of the inputs/outputs.

$\endgroup$
  • $\begingroup$ Spanning switches might indeed be equivalent splitters, nice find. $\endgroup$ – Justin Benfield May 31 '17 at 20:21
  • $\begingroup$ If we have a NxN balancer, it can be used to many a KxK balancer, K<N. If all but K inputs are flowing and all but K outputs are used, then a UTU can, by definition, balance them. The way to achieve this would be to not connect the input/outputs of the balancers and simplify the blueprint by removing unused belts/balancers $\endgroup$ – ZeroUltimax Nov 27 '17 at 16:36
0
$\begingroup$

This might be off from what you are talking about because I am slightly unclear as to what you mean by a 'universally throughput unlimited' Balance.

In my proof I attempt to prove that:

For all natural numbers {n, m} there exists a perfect balance that will take n inputs and m outputs

I interpret Perfect Balance as meaning:

A Balance that, regardless of input throughout each of the n 'belts', will split the given input equally in volume throughout each of the output belts

And just to note: n->m denotes a perfect balance that takes n inputs and m outputs.

First, assume we have n->n.

It can be shown that using this, we can create 2n->2n. Firstly take the first n inputs of the total of 2n and send them through the n->n balance. Take the second set of n inputs of the total of 2n and send them through another parallel n->n balance. If we number the original inputs

{n_1, n_2, n_3 ... n_2n}

The outputs of these two n->n balances would be:

{n_1 / n + n_2 / n + n_3 / n + ... + n_n / n}

For each belt of the first n->n balance, and

{n_n+1 / n + n_n+2 / n + n_n+3 / n + ... + n_2n / n}

For each belt of the second n->n balance. Then simply taking the 1st and n+1th inputs and using a 2->2 balance (This is assumed to exist, as it does in the game) we achieve two belts of output that consist of:

{n_1 / n + n_2 / n + n_3 / n + ... + n_n / n} / 2 +
{n_n+1 / n + n_n+2 / n + n_n+3 / n + ... + n_2n / n} / 2

Which can be seen easily to equal:

{n_1 / (2 * n) + n_2 / (2 * n) + n_3 / (2 * n) + ... + n_2n / (2 * n)}

And hence repeating this 2->2 Split for the 2nd and n+2th belts, 3rd and n+3th belts ... nth and 2nth Gives us perfectly balanced inputs, and hence

Assuming we have n->n, we can create 2n->2n.

Now because the special case of 2->2 exists, by induction,

For all natural numbers {n}, there exists 2^n->2^n

Or in layman terms, all the powers of 2 balances must (and do) exist.

Now the one last piece of the puzzle is extending this to prove we can create n->n assuming m->m exists where n<m. This can be done by taking the m->m, and using n inputs (and hence creating a n->m assuming m->m exists). From this, we take the excess outputs (m-n outputs) and re-input them into the unused m-n inputs (This might require some visualization), and hence create a n->n from a m->m.

Because for all n, there exists m such that n<m and 2^x = m (m is a power of 2) where n, m, x and natural numbers, and we already proved all 2^x->2^x exist (all powers of 2 exist) we can therefore construct all n->n!

In layman terms again, say we want to make a 5->5, we take the 8->8 and take 3 outputs and re-input them into the 3 unused inputs, and hence create the 5->5 we wanted.

I have proven that all n->n exist.

$\endgroup$
  • $\begingroup$ I appreciate the effort you put into this. There is a problem though: it's not as simple as you think to go from an n->n balancer to a 2n->2n balancer. To illustrate the point, consider inputs on k through n and n+k through 2n for some k<n. Your proposed design could not put output on any belt from 1 to k or n to n+k. $\endgroup$ – Justin Benfield Jul 14 '16 at 9:10
  • $\begingroup$ I don't quite understand but thanks for appreciating $\endgroup$ – Kieren Pearson Jul 15 '16 at 3:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.