Factorio: a quantitative guide

Don't know how to use a machine? Looking for efficient setups? Stuck in a mission?
Post Reply
jcranmer
Long Handed Inserter
Long Handed Inserter
Posts: 90
Joined: Wed Jun 29, 2016 9:59 pm
Contact:

Factorio: a quantitative guide

Post by jcranmer »

This is meant to cover quantitative calculations on various throughputs of different Factorio logistics, reduced to the terms of data values as specified in the Lua data files directly so that you can do the math yourself if some of your mods adds different variants with different numbers (most notably Bob's Mods).

Part 0: On how to measure things
This be boring, probabably
Caution: Factorio does have some odd quirks in where things matter. I've tried to notate them when I find them, but entity build order and direction of the grid can have measurable impacts on these numbers.

Part 1: Belts

Belts are the simplest mechanic in the game to measure and time (although I've been told by devs that they are the most complex entities in terms of game code). Each belt has two lanes of items, and each lane consists of a number of slots. A straight length of belt has 32 slots, while the interior curve has 13.5 slots and the exterior has 37 slots. Yes, the interior has a fractional slot: every odd interior curve is 14 slots and every even interior curve is 13 slots. Every item on a belt takes up 9 slots. In terms of prototype data, belts are specified merely by their speed parameter--the number of tiles moved per tick.

The math to compute speed is pretty simple, so I'll work through the entire formula. The number of items per tile is 32/9 × 2, and each belt moves speed × 60 tiles per second--the number of items per second is 32/9 × 2 × speed × 60 items/sec, or 640 / 3× speed. Speed is usually best thought of not in its Lua terms but in slots per second (the base game has yellow belt moving 1 slot per second, red 2, and blue 3), so the simplest way to remember is that blue belt moves 40 items per second, red ⅔ of that and yellow ⅓ of 40 items per second.

Metering a compressed belt will return between 6 and 8 items per straight belt, depending on how long the front of the belt is (7 items is possible, if you have corners in your belts); curved belts are between 5 and 7 items. To get a consistent read, you need to cover multiple tiles--9 tiles of straight belt will hold exactly 64 items. In fact, this is how I worked out the number of slots on curved belts--by working out the necessary extra straight lines to get a constant count, you can deduce the exact number of slots in use.

Making compressed belts isn't so easy, unfortunately. Inserters can't output on a belt if there's not a 9-slot gap. This means the actual loading of a belt before inserters stop can be anywhere between 52% and 100% (simulations suggest the average is closer to about 75-8%). To compress a belt requires that you output to two belts and merge the two belts together. Well, armed with the knowledge I've imparted, there is something else you can do: if you hook up inserters onto a belt every 9th tile, and ensure that they all move in sync, you can output a fully compressed belt--I've tested it, it actually works.

TODO: investigate underground belts, splitters, and sideloading.

Part 2: Inserters

TODO: copy my number tables.

Part 3: Pipes (and fluid mechanics)

In the game, all fluids must be contained in a fluid-box of some kind. Most fluid transfer works by updating these fluid boxes once per tick, as given in the code below.
Fluidbox update pseudocode
To summarize the effects of the pseudo-code, each tick, a fluid box tries to move an amount of fluid between adjacent fluid boxes. This amount is the differences in pressure (effectively, how full it is) times the pressure_to_speed_ratio property plus the amount transferred in that direction last tick times the flow_to_energy property, up to the baseArea. One key thing to note is that the flow energy is not updated when pumps pump into their fluid box.

Actually reading the amounts of fluid in a pipe is difficult to do--the only real way to do it is by using Lua commands. The order that you build pipes matters, too, as well as the pipe directions. There is some scope for handling things out of order (such as, if the amount to be transferred is negative, the game appears to update the transfer amount anyways as if flowing in the opposite direction), but for simplicity I'm going to assume the best case scenario for updates. It's easy to set this scenario up in cheat mode, where you build all pipes from west to east and transfer all fluids from west to east.

Pipe flows have effectively two different flows. The simplest to understand is steady-state flow: as much fluid flows into the pipe as flows out of it; the other flow is the case where fluids are accumulating or draining out of a pipe and will be treated later. In steady-state flow, it follows that the amount transferred in different ticks is the same. This value is goverened by the equation f = (col[p - 1] - col[p]) × pressureToSpeed + min(baseArea, flowToEnergy × f). When f ≤ baseArea ÷ flowToEnergy, some algebra yields that the pressure difference must be f × (1 - flowToEnergy) ÷ pressureToSpeed. In the ideal case, we pump into this connection and then out of it in the same tick, so the difference in pressures is really less that amount by f ÷ baseArea.

Knowing the difference in amounts in adjacent pipes tells us how long the pipe may be before the size of the pipe can no longer accommodate that flow. If we fix the last pipe to have a pressure of 0 (for example, it's the influent pipe to a pump), then after n tiles, the pressure in that pipe is (n - 1) × (f × (1 - flowToEnergy) ÷ pressureToSpeed - f ÷ baseArea). The maximum pressure in a pipe can be 10, and we need to be able to insert f fluid in the head of the pipe on the first tick, so the longest pipe that can accommodate the flow must satisfy the equation (n - 1) × (f × (1 - flowToEnergy) ÷ pressureToSpeed - f ÷ baseArea) + f ÷ baseArea = 10. Solving for n, we get n = 1 + (10 - f ÷ baseArea) ÷ (f × (1 - flowToEnergy) ÷ pressureToSpeed - f ÷ baseArea). If you do the math for vanilla water and pipes and using vanilla small pumps, you get 761 for a single pump, 361 for 2, and 227⅔ for 3--which is fairly close to the numbers presented in the long distance pipes thread (numbers will differ slightly--in part, my experiment found that the final tile did not have a pressure of 0; this may be related to the amount that existed after flow stabilized).

What happens when f ≥ baseArea ÷ flowToEnergy? In this case, the f × flowToEnergy term is reduced to baseArea. The algebraic rearrangement gives us an adjusted formula of (f - baseArea) ÷ pressureToSpeed is the pressure difference, and (n - 1) × ((f - baseArea) ÷ pressureToSpeed - f ÷ baseArea) for the first pipe in that length of pipe. The longest pipe accomdating that flow satisfies (n - 1) × ((f - baseArea) ÷ pressureToSpeed - f ÷ baseArea) + f ÷ baseArea = 10. Solving for n here gives you n = 1 + (10 - f ÷ baseArea) ÷ ((f - baseArea) ÷ pressureToSpeed - f ÷ baseArea). Again, exemplary numbers here for vanilla suggest that 4 small pumps can pump through at most 17 pipes.

We can also solve these equations to find the maximum flow a length of pipe can support. If f ≤ baseArea ÷ flowToEnergy, we get f = 10 × baseArea × pressureToSpeed / (baseArea × (1 - flowEnergy) × (n - 1) - (n - 2) × pressureToSpeed). When f ≥ baseArea ÷ flowToEnergy, we instead get f = baseArea × (baseArea × (n - 1) + 10 × pressureToSpeed) ÷ (baseArea × (n - 1) - (n - 2) × pressureToSpeed).

TODO: Analyze non-steady state solutions.
TODO: Draw conclusions about pipe areas and flows more quantitatively and concretely.

Part 4: Trains
TODO: Coming eventually.

Part 5: Robots
TODO: Coming eventually.

Part 6: Power
TODO: Coming eventually.
Last edited by jcranmer on Sun Oct 09, 2016 5:40 am, edited 1 time in total.

User avatar
steinio
Smart Inserter
Smart Inserter
Posts: 2633
Joined: Sat Mar 12, 2016 4:19 pm
Contact:

Re: Factorio: a quantitative guide

Post by steinio »

Would it not be easier if the devs publish the data?

I guess they should know them best.

Greetings steinio
Image

Transport Belt Repair Man

View unread Posts

User avatar
ssilk
Global Moderator
Global Moderator
Posts: 12888
Joined: Tue Apr 16, 2013 10:35 pm
Contact:

Re: Factorio: a quantitative guide

Post by ssilk »

Very good work. Nice thoughts, good information. :)
I'm nearly sure you read also this (and for the other, that didn't): https://wiki.factorio.com/index.php?tit ... ts/Physics ?

I think this should be moved to Show your Creations, if you have nothing against.
Cause here it will be forgotten: It doesn't match to the target of the board. I would not sticky it here.


Things I want to mention:

I think the term "slot" could be explained better. Maybe in the sense of a stepping-motor? A belt moves one slot per tick (0,03125 tiles/tick)?
It is explained later, but I think the term should be explained when introduced, cause Factorio has also other kinds of "slots".

For the size of the slots: The items on the belts have a size and so you can put only 3 or 4 on a belt, when fully compressed. Each lane on a belt can hold 3.5556 items, which results in either 6, 7 or 8 items on belt, when fully compressed. 7 is also possible, if the two lanes are not running synchronized. In curves - when I calculate right - between 6 and 7 items are possible (4-5 on the outer and 2 on the inner), ...
Well, armed with the knowledge I've imparted, there is something else you can do: if you hook up inserters onto a belt every 9th tile, and ensure that they all move in sync, you can output a fully compressed belt--I've tested it, it actually works.
Interesting find. :o

Did you thought about this: The counter takes 2 ticks to start and stop?

Pipes is also interesting. Well done. I hope the whole pipe-system will be redone soon (The devs promised it more or less).

Moar pictures? Screenshoots from you measuring setups? Blueprints, saves? :)
Cool suggestion: Eatable MOUSE-pointers.
Have you used the Advanced Search today?
Need help, question? FAQ - Wiki - Forum help
I still like small signatures...

jcranmer
Long Handed Inserter
Long Handed Inserter
Posts: 90
Joined: Wed Jun 29, 2016 9:59 pm
Contact:

Re: Factorio: a quantitative guide

Post by jcranmer »

steinio wrote:Would it not be easier if the devs publish the data?
Yes and no. Some of my notes on fluid mechanics literally come from snippets of code a dev gave me, and if you know how to listen, you can glean a lot of internal details--and these are undoubtedly helpful when you get them. On the other hand, there are lots of weird quirks that give off-by-one errors that can accumulate, and those don't necessarily stand out from code. An inserter moving items from south to north is slower than any other direction, for example, (In my tests, it looks like it takes exactly one extra tick per 360° rotation), and that appears to not be obvious from the code itself.
ssilk wrote:Very good work. Nice thoughts, good information. :)
I'm nearly sure you read also this (and for the other, that didn't): https://wiki.factorio.com/index.php?tit ... ts/Physics ?

I think this should be moved to Show your Creations, if you have nothing against.
I read that, but the Factorio wiki unfortunately has the very bad habit of usually being out-of-date. A lot of the discussion on transport belts still talk about slow corners, which hasn't been a problem since 0.12. Similarly, the 0.13 changes to inserters can be difficult to find in most of these number lists. One comment on that page: I definitely recall hearing a dev say that the size of an item on a belt is exactly 9/32 (=0.28125), not the size of item-entity-on-ground (=0.28).

As for moving, I placed it in Gameplay Help largely because that's where I found some prior information posts on this topic (e.g., the pipe physics threads).
I think the term "slot" could be explained better. Maybe in the sense of a stepping-motor? A belt moves one slot per tick (0,03125 tiles/tick)?
It is explained later, but I think the term should be explained when introduced, cause Factorio has also other kinds of "slots".

For the size of the slots: The items on the belts have a size and so you can put only 3 or 4 on a belt, when fully compressed. Each lane on a belt can hold 3.5556 items, which results in either 6, 7 or 8 items on belt, when fully compressed. 7 is also possible, if the two lanes are not running synchronized. In curves - when I calculate right - between 6 and 7 items are possible (4-5 on the outer and 2 on the inner), ...
"Slot" is probably not the best term. How does "segments" sound?
Did you thought about this: The counter takes 2 ticks to start and stop?
The counter has a latency of 2, but the start and stop conditions have the same latency, so it's not a problem. Getting the same latency is why you need the extra arithmetic combinator to multiply by 1. I have some experience getting accurate latency counts out of combinators. :D
Pipes is also interesting. Well done. I hope the whole pipe-system will be redone soon (The devs promised it more or less).

Moar pictures? Screenshoots from you measuring setups? Blueprints, saves? :)
I would love to have a GIF of the compressed belt with inserters set-up, but my video software is currently ruining everything with horrible tearing. I probably need pictures of the inserter setups just to show what I mean when I talk about all the different configurations. Pipes too would be useful to diagram out, since it's too easy to measure the wrong thing. But transport belts are by far the most boring images, just a long belt with a lot of it metered with circuit wire and occasional checks to a power pole to read out the value.

The FFF has started that they plan on "optimizing" pipes and I've heard quotes about them wanting to change fluid mechanics, which makes me reluctant to go too far into minute details until the new plans are released. Over the course of trying to tease out some operational details, I have found two extra fluid properties that are theoretically configurable via Lua, but no documentation makes any mention of them, so I don't know what to make of their likelihood to remain in 0.15.

User avatar
ssilk
Global Moderator
Global Moderator
Posts: 12888
Joined: Tue Apr 16, 2013 10:35 pm
Contact:

Re: Factorio: a quantitative guide

Post by ssilk »

The wiki is outdated, yes, but some changes there are up-to-date, use the history.

For making GIF/Video: I recommend to set the speed via command-line or a mod, that changes the speed.
Cool suggestion: Eatable MOUSE-pointers.
Have you used the Advanced Search today?
Need help, question? FAQ - Wiki - Forum help
I still like small signatures...

jcranmer
Long Handed Inserter
Long Handed Inserter
Posts: 90
Joined: Wed Jun 29, 2016 9:59 pm
Contact:

Re: Factorio: a quantitative guide

Post by jcranmer »

I made some quantitative updates for steady-state pipe flows, backed by experiments. Preliminary investigations (solving multivariate equations for minima and maxima aren't fun, especially when the formula of interest is actually a function with a discontinuous derivative) suggest that the baseArea of a pipe matters far less than you'd think in terms of steady-state flow. The most fun seems to be when you change the fluid values--Tungstic acid (which has a pressureToSpeed of 0.2 and a flowToEnergy of 0.3) produces surprisingly abysmal flow rates, which can be explained largely by the abysmal adjacent column difference it requires to generate flow. I'm now interested to see what happens if you have a high flowToEnergy and low pressureToSpeed or vice versa instead of triggering them in tandem.

User avatar
ssilk
Global Moderator
Global Moderator
Posts: 12888
Joined: Tue Apr 16, 2013 10:35 pm
Contact:

Re: Factorio: a quantitative guide

Post by ssilk »

I updated now the wiki-article: https://wiki.factorio.com/Transport_belts/Physics

What I still don't understand:
jcranmer wrote:Yes, the interior has a fractional slot: every odd interior curve is 14 slots and every even interior curve is 13 slots.
What is the meaning of "odd" and "even"? The number of placed curves? The position (x+y) in tiles?
Cool suggestion: Eatable MOUSE-pointers.
Have you used the Advanced Search today?
Need help, question? FAQ - Wiki - Forum help
I still like small signatures...

User avatar
hansinator
Fast Inserter
Fast Inserter
Posts: 160
Joined: Sat Sep 10, 2016 10:42 pm
Contact:

Re: Factorio: a quantitative guide

Post by hansinator »

Thank you jcranmer for the info. Especially the fluid part is interesting. The thread should be more visible to people who build combinator stuff.
ssilk wrote:What is the meaning of "odd" and "even"? The number of placed curves? The position (x+y) in tiles?
Only the number makes sense, otherwise you wouldn't get the 0.5 fraction on average.
Edit: The number must be a local property of course, not the global number of placed curves. I believe it is the number of curves the item has traversed since it is moving on the same belt. So it would be an per-item-on-belt property. Internally this may be represented by a fractional slot, i.e. after traversing an inner curve the item may be in a belt tiles slot 24.5 for example. Outer curves and straight segments only add integers, so the fraction would stay until the next curve. This way an item would have a fractional slot coordinate after traversing the first inner curve. It would even out at the second, become fractional on the third, and so on.. resulting in the even/odd number pattern.

AcolyteOfRocket
Fast Inserter
Fast Inserter
Posts: 124
Joined: Sun Mar 06, 2016 9:58 pm
Contact:

Re: Factorio: a quantitative guide

Post by AcolyteOfRocket »

Very interesting - moar ! ...

.. but I do understand your reasons for delaying until the game settles down a bit :D

jcranmer
Long Handed Inserter
Long Handed Inserter
Posts: 90
Joined: Wed Jun 29, 2016 9:59 pm
Contact:

Re: Factorio: a quantitative guide

Post by jcranmer »

My notes for computing robot throughput. I don't have the time right now to actually type it up into something coherent, but hopefully this will let me remember what the actual formulas and equations are supposed to be:
(NB: kŴ is funky notation I invented to represent kJ / tick).

Code: Select all

every 4 tiles, 4 slots

Power = 0.05kJ / tick + 5 kJ / tile * 0.05 tiles / tick * ROBO_SPEED
P = 0.05kŴ + 0.25kŴ * ROBO_SPEED

E(dist) = P * time to move dist = P * dist / speed
        = P / (0.05 tiles/tick * ROBO_SPEED) * dist tiles
        = (0.05 kŴ + 0.25kŴ * ROBO_SPEED) / (...) * dist
        = (1 kJ / tile + 5 kJ / tile * ROBO_SPEED) / (ROBO_SPEED) * dist
        = (1 kJ / ROBO_SPEED + 5 kJ) * dist

Recharge_dist = 1125 kJ / (1kJ / ROBO_SPEED + 5 kJ)
Recharge_time = Recharge_dist / (0.05 tiles/tick * ROBO_SPEED)
              = 1125 kJ / (1 kJ + 5 kJ * ROBO_SPEED) / 0.05
              = 22500 / (1 + 5 * ROBO_SPEED) ticks
              = 375 / (1 + 5 * ROBO_SPEED) seconds

Charge_time = 1125 kJ / 1 MW = 1.125 seconds
Charge_distance = 1.125 sec * 60 ticks / sec * 0.05 tiles / tick * ROBO_SPEED
                = 3.375 tiles * ROBO_SPEED

Robots per charge spot = 1 + Recharge_time / Charge_time
                       = 1 + 1000 / 3 * 1 / (1 + 5 * ROBO_SPEED) robots

capacity(dist) = 12 * ROBO_SPEED / dist

1.5 MJ * .75 = E(dist)

Post Reply

Return to “Gameplay Help”