Factorio Kwaliteit Oplossen

Ik speel Factorio op de normale manier: door matrixwiskunde-code te schrijven om de fabriek te plannen. Maar daar komen we nog op terug. (Voor wie dat liever niet wil: ga direct naar mijn nieuwe online calculator-tool).

Introductie tot Factorio en Kwaliteit

Factorio heeft in feite het genre van de fabrieks-videogames gesticht: je speelt een personage dat grondstoffen verzamelt en combineert om steeds complexere items te maken, die op hun beurt weer geavanceerdere productie mogelijk maken.

Tot nu toe klinkt dit veel als Minecraft en andere survivalgames, maar wat fabrieksgames onderscheidt, is de focus op automatisering. Al snel wordt het grootste deel van het vakmanschap niet "met de hand" gedaan door het personage, maar door een groeiend aantal machines, met diverse vormen van logistiek zoals transportbanden om items tussen machines of naar hun bestemming te verplaatsen. Sommige fabrieksgames gaan verder en verwijderen het spelpersonage volledig.

Naarmate "technologieën" in het spel worden ontgrendeld, biedt Factorio verschillende mechanismen om de productie te verbeteren. Eén daarvan zijn modules: productiemachines hebben een beperkt aantal slots voor verschillende soorten modules die hun statistieken beïnvloeden:

  • Snelheidsmodules zorgen ervoor dat de machine sneller draait, ten koste van een hoger energieverbruik.
  • Productiviteitsmodules verhogen de opbrengst uit dezelfde ingrediënten, ten koste van snelheid en energie.

De in 2024 uitgebrachte Space Age-uitbreiding voegt nieuwe spelmechanieken toe, waaronder Kwaliteit (Quality). Elk item en recept komt nu voor in vijf kwaliteitsniveaus: <0xE2><0x9A><0x80> normaal, <0xE2><0x9A><0x81> ongebruikelijk, <0xE2><0x9A><0x82> zeldzaam, <0xE2><0x9A><0x83> episch, en <0xE2><0x9A><0x84> legendarisch.

Afhankelijk van het item verbetert elk niveau bepaalde statistieken, zoals het sneller maken van productiemachines of het verhogen van de effectiviteit van productiviteitsmodules. Items van hoge kwaliteit kunnen direct worden gemaakt van ingrediënten van dezelfde kwaliteit, maar de enige manier om de kwaliteit te verhogen is via de nieuwe kwaliteitsmodules. Kwaliteitsmodules kunnen zelf ook een kwaliteit hebben.

Modules beïnvloeden de kans $Q$ op een kwaliteitsverhoging. Voor een specifiek productieproces is elke kwaliteitsverhoging na de eerste stap een kans van 10%.

Er kan een tabel worden opgesteld van de kansen op outputkwaliteit afhankelijk van de inputkwaliteit (bron: Factorio wiki). Bijvoorbeeld, de maximale mogelijke kwaliteitskans in een machine met vier moduleslots is 24,8%. De kans om in één stap van normaal naar legendarisch te springen, is slechts 0,0248%.

Sommige spelers hebben een hekel aan de introductie van willekeur in een spel dat grotendeels deterministisch was, maar bij voldoende herhalingen worden kansen ratio's. De kansen zijn zo gebalanceerd dat, zelfs met meerdere productiestappen (waarvan elke stap een potentiële kwaliteits sprong is), het verkrijgen van items van hoge kwaliteit onvermijdelijk gepaard gaat met het maken van veel ongewenste items van lage kwaliteit.

Om te voorkomen dat de fabriek tot stilstand komt wanneer de opslag vol raakt, introduceert Space Age ook de recycler: een nieuwe machine die elk item vernietigt en (meestal) 25% van de ingrediënten teruggeeft. Dit stelt spelers in staat om "upcycling"-constructies te ontwerpen die produceren en recyclen in een loop met kwaliteitsmodules, totdat items de gewenste kwaliteit bereiken, ten koste van het verbruik van veel meer ingrediënten.

Fabrieksplanning-tools

Sommige videogames worden gedeeltelijk "buiten" het spel zelf gespeeld. Blue Prince verwacht bijvoorbeeld dat spelers uitgebreide aantekeningen maken van alles wat ze zien, maar biedt geen in-game notitieblok. Fabrieksgames lenen zich uitstekend voor het maken van grote spreadsheets voor grondstoffenboekhouding. Een selecte groep spelers vindt spreadsheets echter niet krachtig genoeg voor fabrieksplanning en besteedt talloze uren aan het programmeren van speciale tools die veel van de wiskunde van het spel reproduceren om een productieketen nauwkeurig te modelleren.

Dit is allemaal optioneel; het is volkomen mogelijk om op gevoel te spelen en simpelweg meer te bouwen wanneer er iets tekort is. Maar ik hou ervan om vooruit te plannen: hoeveel machines van elk type heb ik nodig? Welke opbrengst kan ik verwachten? Waar zitten de bottlenecks? De cyclische aard van kwaliteits-upcycling maakt dit bijzonder uitdagend om te gokken of te berekenen met bestaande tools.

Matrixwiskunde

Stel je het volgende voor:

  1. Enkele ingrediënten (bijvoorbeeld ijzeren platen) die komen uit een willekeurige productieketen die kwaliteitsmodules kan bevatten. Elk ingrediënt heeft een kans om in elk kwaliteitsniveau te zijn: <0xE2><0x9A><0x80> normaal, <0xE2><0x9A><0x81> ongebruikelijk, <0xE2><0x9A><0x82> zeldzaam, <0xE2><0x9A><0x83> episch, en <0xE2><0x9A><0x84> legendarisch.
  2. Voldoende assemblagemachines met elk receptniveau om alle ingrediënten om te zetten in een product (bijvoorbeeld pijpen). Deze machines hebben kwaliteitsmodules waardoor de kwaliteitskans 10% is.

Laten we het mogelijke lot van één item volgen. Een product van een bepaald niveau kan voortkomen uit ingrediënten van hetzelfde niveau of lager. De totale kans voor deze uitkomst is de som van de (onafhankelijke) kansen van verschillende manieren om dit te bereiken. Op hun beurt zijn dit het product van de procentuele kans op een specifieke kwaliteitssprong vermenigvuldigd met de kans dat men het corresponderende ingrediëntniveau in de eerste plaats had:

$$ \begin{align} p<0xE2><0x9A><0x80> &= i<0xE2><0x9A><0x80> � 90\% \\ p<0xE2><0x9A><0x81> &= i<0xE2><0x9A><0x80> � 9\% &+ &i<0xE2><0x9A><0x81> � 90\% \\ p<0xE2><0x9A><0x82> &= i<0xE2><0x9A><0x80> � 0.9\% &+ &i<0xE2><0x9A><0x81> � 9\% &+ &i<0xE2><0x9A><0x82> � 90\% \\ p<0xE2><0x9A><0x83> &= i<0xE2><0x9A><0x80> � 0.09\% &+ &i<0xE2><0x9A><0x81> � 0.9\% &+ &i<0xE2><0x9A><0x82> � 9\% &+ &i<0xE2><0x9A><0x83> � 90\% \\ p<0xE2><0x9A><0x84> &= i<0xE2><0x9A><0x80> � 0.01\% &+ &i<0xE2><0x9A><0x81> � 0.1\% &+ &i<0xE2><0x9A><0x82> � 1\% &+ &i<0xE2><0x9A><0x83> � 10\% &+ i<0xE2><0x9A><0x84> \end{align} $$

(Het procentteken kan worden beschouwd als een impliciete deling door 100, zodat "percentage van" hetzelfde is als vermenigvuldiging.)

Hier lijken de procentuele coëfficiënten getransponeerd over de diagonaal vergeleken met de kwaliteitsprong-tabel uit de wiki, maar dat komt alleen omdat we de productniveaus verticaal hebben gerangschikt. Laten we in plaats daarvan de kansen van verschillende niveaus van hetzelfde item groeperen in rijvectoren:

$$ \begin{align} product &= \begin{pmatrix} p<0xE2><0x9A><0x80> & p<0xE2><0x9A><0x81> & p<0xE2><0x9A><0x82> & p<0xE2><0x9A><0x83> & p<0xE2><0x9A><0x84> \end{pmatrix} \\ ingredient &= \begin{pmatrix} i<0xE2><0x9A><0x80> & i<0xE2><0x9A><0x81> & i<0xE2><0x9A><0x82> & i<0xE2><0x9A><0x83> & i<0xE2><0x9A><0x84> \end{pmatrix} \\ \end{align} $$

Nu kan ons systeem van lineaire vergelijkingen worden geschreven als één vergelijking waarbij een vector wordt vermenigvuldigd met een transitiematrix die overeenkomt met de tabel in de wiki:

$$ \begin{align} {products} &= {ingredients} � T{quality}(10\%) \\[1em] T{quality}(q) &= \begin{pmatrix} 1-q & \frac{9q}{10} & \frac{9q}{100} & \frac{9q}{1000} & \frac{q}{1000} \\[0.3em] 0 & 1-q & \frac{9q}{10} & \frac{9q}{100} & \frac{q}{100} \\[0.3em] 0 & 0 & 1-q & \frac{9q}{10} & \frac{q}{10} \\[0.3em] 0 & 0 & 0 & 1-q & q \\[0.3em] 0 & 0 & 0 & 0 & 1 \end{pmatrix} \end{align} $$

Als randgeval betekent een kwaliteitskans van nul dat er geen niveau-transformatie plaatsvindt. De corresponderende transitiematrix is de identiteitsmatrix: $T{quality}(0\%) = I5$.

Dit lijkt misschien niet veel vooruitgang, maar nu kan een proces met meerdere stappen worden berekend via opeenvolgende matrixvermenigvuldigingen. Bijvoorbeeld: ijzererts mijnen met 7,5% kwaliteitskans, dit smelten tot ijzeren platen met 5% kwaliteitskans, en vervolgens pijpen maken met 10% kans. Zonder productiviteitsbonus krijgen we deze kansen voor de eindproducten:

$$ \begin{align} pipe &= \begin{pmatrix} 1 & 0 & 0 & 0 & 0 \end{pmatrix*} �

T_{quality}(7.5\%) �

T_{quality}(5\%) �

T_{quality}(10\%) \\ &= \begin{pmatrix} 0.925 & 0.0675 & 0.00675 & 0.000675 & 0.000075 \end{pmatrix} �

T_{quality}(5\%) �

T_{quality}(10\%) \\ &≈ \begin{pmatrix} 0.87875 & 0.10575 & 0.013613 & 0.001665 & 0.000223 \end{pmatrix} �

T_{quality}(10\%) \\ &≈ \begin{pmatrix} 0.790875 & 0.174263 & 0.029678 & 0.004467 & 0.000719 \end{pmatrix} \end{align*} $$

Kwaliteitsstrategieën

Hoewel het mogelijk is om kwaliteitsmodules zoveel mogelijk te gebruiken en elk niveau tegelijkertijd aan te pakken, focussen we hier op kleinere, zelfstandige systemen.

"Gokken": Opportunistische kwaliteit zonder recycling

De makkelijkste maar minst effectieve methode is om te produceren met ingrediënten van normale kwaliteit en kwaliteitsmodules, zonder iets te recyclen. Dit kan voordat de recycler is ontgrendeld, maar is alleen levensvatbaar voor een klein aantal items (zoals het maken van een paar honderd asteroïde-collectors in de hoop een dozijn ongebruikelijke of zeldzame te krijgen voor een vroeg ruimteschip).

Dit is verbeterd wanneer de fabriek een ander gebruik heeft voor items van normale kwaliteit. Als men bijvoorbeeld duizenden normale zonnepanelen plaatst, geeft het produceren ervan met kwaliteitsmodules een betere opbrengst van hogere kwaliteiten voor ruimteschepen voordat de outputbuffers vol raken. Bij één stap zonder loop is dit het eenvoudigst te berekenen: de verwachte productverdeling is de eerste rij van de $T_{quality}(q)$ transitiematrix of de kansentabel in de wiki.

"Wassen": Pure recycling-loop

Voor de meeste items keert de recycler het hoofdrecept om en geeft 25% van de ingrediënten terug. Sommige items hebben echter geen productierecept (zoals erts) of het proces wordt als onomkeerbaar beschouwd (meestal smelten en chemische processen). In dat geval produceert de recycler niets, of, in 25% van de gevallen, hetzelfde item.

Dit proces kan de kwaliteit verbeteren als de recycler kwaliteitsmodules heeft. Door dit in een loop te herhalen, zullen uiteindelijk alle items ofwel vernietigd worden of verbeterd worden totdat ze een gewenst kwaliteitsniveau bereiken.

Zelf-recycling is wellicht niet het meest voorkomende geval, maar we beginnen hier omdat de wiskunde eenvoudiger is. Voorbeeldopstelling: erts mijnen (met kwaliteitsmodules) en dit "wassen" tot zeldzaam of hoger.

Laten we één item overwegen dat in het systeem wordt gebracht via mijnbouw, en noemen $\text{fresh}_{unit}$ de 5-componenten rijvector van kansen per kwaliteitsniveau. Na de transformatie van die vector kunnen de nieuwe kansen minder dan één bedragen. De impliciete resterende case is dat er op een bepaald punt helemaal geen item meer is. Bijvoorbeeld, een recycler die 75% van de tijd niets produceert, kan worden weergegeven door een vector van kansen te vermenigvuldigen met $\frac{1}{4}$.

Filtering op basis van kwaliteit kan ook worden weergegeven met matrixvermenigvuldiging. In het geval van het extraheren van zeldzaam of hoger:

$$ \begin{align} T{filterKeep} &= \begin{pmatrix} 1 & 0 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 \end{pmatrix} \\ T{filterExtract} &= \begin{pmatrix} 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 0 & 1 \end{pmatrix} = I5 - T{filterKeep} \end{align} $$

Het gecombineerde effect van één iteratie door de loop is filtering om te behouden, gevolgd door recycling met kwaliteit: $L = T{filterKeep} \cdot \frac{1}{4} \cdot T{quality}(q)$.

De mogelijke manieren waarop een item kan worden geëxtraheerd zijn:

  1. Het had oorspronkelijk een hoge genoeg kwaliteit om direct geëxtraheerd te worden: $\text{fresh}{unit} \cdot T{filterExtract} = \text{fresh}{unit} \cdot L^0 \cdot T{filterExtract}$.
  2. Het ging precies één keer door de recycling-loop: $\text{fresh}{unit} \cdot T{filterKeep} \cdot L \cdot T{filterExtract} = \text{fresh}{unit} \cdot L^1 \cdot T_{filterExtract}$.
  3. Het ging precies twee keer door de recycling: $\text{fresh}{unit} \cdot T{filterKeep} \cdot L \cdot L \cdot T{filterExtract} = \text{fresh}{unit} \cdot L^2 \cdot T_{filterExtract}$, enzovoort.

Elk item zal uiteindelijk worden geëxtraheerd of vernietigd, maar er is geen bovengrens aan het aantal loops. De combinatie van alle mogelijke uitkomsten is een oneindige som:

$$ \text{extracted}{unit} = \text{fresh}{unit} \cdot \bigg(\sum{i=0}^{+\infty} L^i\bigg) \cdot T{filterExtract} $$

Oneindige sommen zijn onhandig om in eindige tijd te berekenen, hoewel deze convergeert naar een eindige waarde omdat de termen exponentieel kleiner worden. We zouden kunnen berekenen tot de termen klein genoeg zijn voor een benadering, maar dat is onbevredigend wanneer een exacte oplossing mogelijk is.

Gemiddelde doorvoersnelheid op lange termijn

Het belangrijkste inzicht is dat het niet uitmaakt hoe vaak een specifiek item al door de loop is gegaan, alleen welk kwaliteitsniveau het nu heeft. Op korte termijn zal dit variëren door het willekeurige effect van kwaliteitsmodules, maar bij voldoende herhalingen worden kansen ratio's.

In plaats van kansen voor een enkel item, beschouwen we de gemiddelde snelheid van items over een voldoende lange periode die door een bepaald deel van het systeem gaan, wederom als een 5-componenten vector voor kwaliteitsniveaus.

In het geval van een "wassen" pure recycling-loop zijn de relevante vectoren:

  • fresh: nieuwe items die in het systeem worden gebracht, met een willekeurige kwaliteitsverdeling (in dit voorbeeld gebaseerd op kwaliteitsmodules in miners).
  • fromRecycling: items uit de recycling.
  • splitter: alle items die door de splitter gaan.
  • extracted: items geëxtraheerd op basis van hun kwaliteitsniveau (bijv. zeldzaam of hoger).
  • toRecycle: items die met kwaliteit $q$ gerecycled worden, dus die niet geëxtraheerd zijn.

Het systeem convergeert naar een dynamisch evenwicht waarbij de volgende vergelijkingen gelden voor gemiddelden op lange termijn: $$ \begin{align} splitter &= fresh + fromRecycling \\ splitter &= extracted + toRecycle \\ extracted &= splitter � T{filterExtract} \\ toRecycle &= splitter � T{filterKeep} \\ fromRecycling &= toRecycle � \frac{1}{4} T_{quality}(q) \end{align} $$

Door substitutie krijgen we: $$ \begin{align} splitter &= fresh + fromRecycling \\ splitter - fromRecycling &= fresh \\ splitter - toRecycle � \frac{1}{4} T{quality}(q) &= fresh \\ splitter - splitter � T{filterKeep} � \frac{1}{4} T{quality}(q) &= fresh \\ splitter � (I5 - T{filterKeep} � \frac{1}{4} T{quality}(q)) &= fresh \end{align} $$

Om aan de klassieke conventie te voldoen, transponeren we dit naar kolomvectoren: $$ (I5 - T{filterKeep} � \frac{1}{4} T_{quality}(q))^T � splitter^T = fresh^T $$

We introduceren nieuwe namen: $A = (I5 - T{filterKeep} � \frac{1}{4} T_{quality}(q))^T$, $x = splitter^T$ en $b = fresh^T$. Nu hebben we een systeem van lineaire vergelijkingen in de klassieke vorm $A \cdot x = b$, dat we kunnen oplossen voor $x$ middels Gauss-eliminatie. Vanuit $x$ kunnen we eenvoudig splitter, toRecycle (voor het aantal benodigde recyclers) en extracted (voor de totale opbrengst) berekenen.

Als de voorbeeldopstelling zou worden geschaald om 100 erts per seconde te mijnen, met $q = 10\%$ en extractie van $\geq$ zeldzaam, is de oplossing:

  • toRecycle $\approx (116.1291, 14.9844, 0, 0, 0)$
  • extracted $\approx (0, 0, 1.4985, 0.1499, 0.0167)$

Omgerekend per minuut betekent dit een opbrengst van ongeveer 90 zeldzame, 9 epische en 1 legendarische items.

Voor een ander voorbeeld: injectie van alleen normale kwaliteitsitems, recycling met de beste beschikbare modules ($q = 24,8\%$) en extractie van alleen legendarische items. De oplossing laat zien dat men gemiddeld $\approx 2726,91$ normale kwaliteitsinputs nodig heeft voor elke legendarische output.

"Upcycling": Crafting- en recycling-loop

Voor items waarbij recycling ingrediënten teruggeeft, kunnen we productiemachines koppelen aan recyclers om een loop te vormen.

We abstraheren hierbij "de set ingrediënten voor één craft" als de basiseenheid. We meten de gemiddelde snelheden van ingrediënten en producten op lange termijn.

Voor ingrediënten beschouwen we:

  • freshI: in het systeem geïnjecteerde ingrediënten.
  • fromRecycling: ingrediënten uit recycling.
  • totalI: totale ingrediënten.
  • extractedI: geëxtraheerde ingrediënten.
  • toCraft: ingrediënten om nieuwe producten van te maken.

Voor producten beschouwen we:

  • freshP: geïnjecteerde producten.
  • fromCrafting: producten uit productie.
  • totalP: totale producten.
  • extractedP: geëxtraheerde producten.
  • toRecycle: producten om te recyclen.

We houden rekening met een productiviteitsbonus (productivityBonus) en het feit dat de kwaliteitskans kan verschillen tussen productie en recycling. We definiëren: $T{craft} = (1 + productivityBonus) \cdot T{quality}(q{crafting})$ $T{recycle} = \frac{1}{4} T{quality}(q{recycling})$

Het systeem convergeert naar een evenwicht: $$ \begin{align} totalI &= freshI + fromRecycling \\ totalI &= extractedI + toCraft \\ extractedI &= totalI � T^{ingredients}{filterExtract} \\ toCraft &= totalI � T^{ingredients}{filterKeep} \\ fromCrafting &= toCraft � T{craft} \\[2em] totalP &= freshP + fromCrafting \\ totalP &= extractedP + toRecycle \\ extractedP &= totalP � T^{products}{filterExtract} \\ toRecycle &= totalP � T^{products}{filterKeep} \\ fromRecycling &= toRecycle � T{recycle} \end{align} $$

Door substitutie reduceren we dit wederom tot de vorm $A \cdot x = b$: $A = (I5 - T{filterRecycle} \cdot T{filterCraft})^T$ $x = totalP^T$ $b = (freshP + freshI \cdot T{filterCraft})^T$

In een praktijkvoorbeeld voor het upcyclen van constructierobots naar legendarisch (bij $q = 24,8\%$ voor zowel craft als recycle, en bonus = 0%), is de bottleneck de productiesnelheid van normale producten (360 per minuut). De resultaten tonen aan dat dit systeem gemiddeld bijna 2 legendarische constructierobots per minuut produceert en ongeveer 309 sets ingrediënten per minuut verbruikt.

Voor sommige items in Space Age kan de productiviteitsbonus via onderzoek worden verhoogd tot een harde limiet van +300%. Dit zorgt ervoor dat productie gevolgd door recycling maximaal de ingrediënten teruggeeft waarmee men begon, nooit meer. Bij een maximale bonus van +300% en recycling met $q = 24,8\%$ (maar $q=0\%$ bij productie), kan een product van normale kwaliteit worden omgezet in een legendarisch product zonder verlies van grondstoffen, al gaat dit ten koste van veel machines en modules.

"Space Casino": Asteroïde-herverwerking

In Space Age is elk ruimteplatform een minifabriek. In plaats van erts uit de grond te mijnen, verzamelen ze asteroïde-brokken en verbrijzelen ze deze. Er zijn drie typen brokken (metallisch, carbonisch en oxide). Deze kunnen worden "herverwerkt" (reprocessed) voor een kans om een ander type te krijgen (of niets).

Dit proces kan wiskundig worden weergegeven als het vermenigvuldigen van een rijvector met een 3x3 transitiematrix $T_{reprocessing}$, waarbij de kansen 40% zijn voor het behouden van het type en 20% voor de overige twee typen.

Herverwerking accepteert ook kwaliteitsmodules, dus het kan in een loop worden gebruikt, vergelijkbaar met "wassen". Omdat we drie typen brokken hebben in elk van de vijf kwaliteitsniveaus, werken we met 15-componenten vectoren en 15x15 transitiematrices. Deze laatste worden opgebouwd als blokmatrices bestaande uit negen 5x5 blokken.

De wiskunde is identiek aan die van het "wassen" en leidt opnieuw tot een $A \cdot x = b$ systeem.

Asteroïde-verbrijzelaars hebben twee moduleslots, dus de beste kwaliteitskans voor herverwerking is $q = 12,4\%$. Asteroïde-collectors hebben geen slots, dus vers verzamelde brokken zijn altijd van normale kwaliteit.

Bijvoorbeeld: in de baan om Nauvis, waarbij alleen legendarische oxide-brokken worden geëxtraheerd en de rest wordt herverwerkt. We observeren dat naarmate het kwaliteitsniveau stijgt, de verdeling van asteroïdetypen snel convergeert naar een gelijke verdeling van $1/3$ per type.

De legendarische opbrengst is ongeveer $1/71,5 \approx 1,4\%$ van de totale verse input. Dit is veel beter dan de $\approx 1/2726$ bij pure recycling, omdat herverwerking de input slechts in 20% van de gevallen vernietigt, tegenover 75% bij recycling.

Andere Strategieën

Er zijn andere manieren om kwaliteitsitems te verkrijgen die niet in bovenstaande categorieën passen (zoals "The LDS Shuffle"). Maar als een loop het berekenen van het gedrag bemoeilijkt, kunnen we dezelfde principes toepassen:

  1. Representeer de doorvoersnelheid van verschillende soorten items als vectoren.
  2. Representeer lineaire transformaties (productie, recycling, etc.) als matrixvermenigvuldigingen.
  3. Representeer het dynamisch evenwicht als een matrixvergelijking.
  4. Los de vergelijking op, indien nodig met Gauss-eliminatie.

Het maken van een interactieve calculator

Matrixwiskunde met de hand is tijdrovend en foutgevoelig. Ik begon met Rust en de bibliotheek nalgebra. Hoewel floating-point getallen (f32 of f64) voldoende zouden zijn, introduceren ze precisiefouten. Om exact resultaten te krijgen, heb ik gekozen voor rationele getallen (gepresenteerd als een paar integers). Met i128 en overflow-checks was dit voldoende voor 15x15 matrices.

Om de tool toegankelijk te maken, heb ik de logica herschreven in TypeScript om deze in de browser te kunnen draaien. Ik heb gebruikgemaakt van:

  • BigInt (ingebouwd in JS) voor precisie.
  • Een rationele bibliotheek (gebaseerd op Factoriolab).
  • VanJS voor minimale reactiviteit in de GUI.
  • Vite voor TypeScript en development.
  • Grebedoc voor hosting.

Het resultaat is factoqual.grebedoc.dev, een interactieve GUI voor het plannen van Quality upcyclers. De broncode is beschikbaar op codeberg.org/SimonSapin/factoqual.

Erkenningen

Ik ben sterk geïnspireerd door de blogposts van Daniel Monteiro over kwaliteitswiskunde. Anderen hebben soortig werk verricht, waaronder Konage en bijdragers aan de Factorio wiki. Ik geloof echter dat de exacte oplossing via de evenwichtvergelijking, zoals hier getoond, nieuw is, in tegenstelling tot iteratieve benaderingen van een oneindige som.