Commiting some old changes
This commit is contained in:
parent
0bb81bfc46
commit
3f6091369a
5
purescript/factorio-throughput/.gitignore
vendored
5
purescript/factorio-throughput/.gitignore
vendored
|
@ -9,3 +9,8 @@
|
||||||
/.psa*
|
/.psa*
|
||||||
/.spago
|
/.spago
|
||||||
dist
|
dist
|
||||||
|
*.aux
|
||||||
|
*.fls
|
||||||
|
*.fdb_*
|
||||||
|
*.synctex*
|
||||||
|
*.log
|
||||||
|
|
BIN
purescript/factorio-throughput/idea/example.pdf
Normal file
BIN
purescript/factorio-throughput/idea/example.pdf
Normal file
Binary file not shown.
94
purescript/factorio-throughput/idea/example.tex
Normal file
94
purescript/factorio-throughput/idea/example.tex
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
\documentclass[a4paper, 12pt]{article}
|
||||||
|
|
||||||
|
\newcommand{\bold}{\textbf}
|
||||||
|
|
||||||
|
\usepackage[english]{babel}
|
||||||
|
\usepackage{amsmath}
|
||||||
|
\usepackage{tikz}
|
||||||
|
\usepackage{indentfirst}
|
||||||
|
|
||||||
|
\begin{document}
|
||||||
|
|
||||||
|
\newcommand{\q2}{\quad\quad}
|
||||||
|
|
||||||
|
\title{\Large{\bold{Moontorio}}}
|
||||||
|
\author{Matei Adriel}
|
||||||
|
\date {}
|
||||||
|
|
||||||
|
\maketitle
|
||||||
|
|
||||||
|
\section{Example 1}
|
||||||
|
|
||||||
|
Solve the following factory:
|
||||||
|
|
||||||
|
\vspace*{20pt}
|
||||||
|
\begin{figure}[h]
|
||||||
|
\centering
|
||||||
|
\begin{tikzpicture}[shorten >=1pt, auto, node distance={30mm},
|
||||||
|
main/.style = {draw, rectangle}]
|
||||||
|
|
||||||
|
\node[main] (3) {$consumer_1$};
|
||||||
|
\node[main] (1) [above left of=3] {$provider_1$};
|
||||||
|
\node[main] (2) [below left of=3] {$provider_2$};
|
||||||
|
\node[main] (4) [right of=2] {$consumer_2$};
|
||||||
|
|
||||||
|
\draw[->] (1) edge node{$p_1$} (3);
|
||||||
|
\draw[->] (2) edge node{$p_2$} (3);
|
||||||
|
\draw[->] (2) edge node{$p_3$} (4);
|
||||||
|
|
||||||
|
\end{tikzpicture}
|
||||||
|
\caption{Factory}
|
||||||
|
\label{fig:Factory}
|
||||||
|
\end{figure}
|
||||||
|
|
||||||
|
Generating the constraints:
|
||||||
|
\begin{figure}[h]
|
||||||
|
\centering
|
||||||
|
|
||||||
|
\begin{equation}
|
||||||
|
p_1(t) < provider_1(t)
|
||||||
|
\end{equation}
|
||||||
|
|
||||||
|
\begin{equation}
|
||||||
|
p_3(t) < consumer_2(t)
|
||||||
|
\end{equation}
|
||||||
|
|
||||||
|
\begin{equation}
|
||||||
|
\begin{split}
|
||||||
|
\begin{cases}
|
||||||
|
\begin{cases}
|
||||||
|
p_2(t) &< \displaystyle\frac{consumer_1(t)}{2}\\
|
||||||
|
p_1(t) &< consumer_1(t) - p_2(t)
|
||||||
|
\end{cases}
|
||||||
|
\ ,&\;\mbox{if } p_1(t) \geq p_2(t)\\\\
|
||||||
|
\begin{cases}
|
||||||
|
p_1(t) &< \displaystyle\frac{consumer_1(t)}{2}\\
|
||||||
|
p_2(t) &< consumer_1(t) - p_1(t)
|
||||||
|
\end{cases}
|
||||||
|
\ ,&\;\mbox{if } p_1(t) < p_2(t)
|
||||||
|
\end{cases}
|
||||||
|
\end{split}
|
||||||
|
\end{equation}
|
||||||
|
|
||||||
|
\begin{equation}
|
||||||
|
\begin{split}
|
||||||
|
\begin{cases}
|
||||||
|
\begin{cases}
|
||||||
|
p_3(t) &< \displaystyle\frac{provider_2(t)}{2}\\
|
||||||
|
p_2(t) &< provider_2(t) - p_3(t)
|
||||||
|
\end{cases}
|
||||||
|
\ ,&\;\mbox{if } p_2(t) \geq p_3(t)\\\\
|
||||||
|
\begin{cases}
|
||||||
|
p_2(t) &< \displaystyle\frac{provider_2(t)}{2}\\
|
||||||
|
p_3(t) &< provider_2(t) - p_3(t)
|
||||||
|
\end{cases}
|
||||||
|
\ ,&\;\mbox{if } p_2(t) < p_3(t)
|
||||||
|
\end{cases}
|
||||||
|
\end{split}
|
||||||
|
\end{equation}
|
||||||
|
|
||||||
|
\caption{Constraints}
|
||||||
|
\label{fig:Constraints}
|
||||||
|
\end{figure}
|
||||||
|
|
||||||
|
\end{document}
|
BIN
purescript/factorio-throughput/idea/hmm.pdf
Normal file
BIN
purescript/factorio-throughput/idea/hmm.pdf
Normal file
Binary file not shown.
77
purescript/factorio-throughput/idea/hmm.tex
Normal file
77
purescript/factorio-throughput/idea/hmm.tex
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
\documentclass[a4paper, 12pt]{article}
|
||||||
|
|
||||||
|
\newcommand{\bold}{\textbf}
|
||||||
|
|
||||||
|
\usepackage[english]{babel}
|
||||||
|
\usepackage{amsmath}
|
||||||
|
\usepackage{tikz}
|
||||||
|
\usepackage{indentfirst}
|
||||||
|
|
||||||
|
\begin{document}
|
||||||
|
|
||||||
|
\newcommand{\q2}{\quad\quad}
|
||||||
|
|
||||||
|
\title{\Large{\bold{Moontorio}}}
|
||||||
|
\author{Matei Adriel}
|
||||||
|
\date {}
|
||||||
|
|
||||||
|
\maketitle
|
||||||
|
|
||||||
|
\section{Describing a factory}
|
||||||
|
|
||||||
|
A factory is made out of machines. A machine is either a provider, a belt or a consumer. Machines are connected by ports.
|
||||||
|
|
||||||
|
\begin{figure}[h]
|
||||||
|
|
||||||
|
\begin{equation}
|
||||||
|
\begin{split}
|
||||||
|
Machines\ A,\ B,\ C\ &::=\; belt\ p_i\ p_o \\
|
||||||
|
&\quad|\quad provider\ p_1,\ p_2,\ ...\ p_n \\
|
||||||
|
&\quad|\quad consumer\ p_1,\ p_2,\ ...\ p_n
|
||||||
|
\end{split}
|
||||||
|
\end{equation}
|
||||||
|
\caption{Machines}
|
||||||
|
\label{Machines}
|
||||||
|
\end{figure}
|
||||||
|
|
||||||
|
We can represent the factory as a directed graph, with the machines being the nodes and the ports being the edges:
|
||||||
|
|
||||||
|
\vspace*{20pt}
|
||||||
|
\begin{figure}[h]
|
||||||
|
\centering
|
||||||
|
\begin{tikzpicture}[shorten >=1pt, auto, node distance={50mm},
|
||||||
|
main/.style = {draw, rectangle}]
|
||||||
|
|
||||||
|
\node[main] (1) {$provider_1$};
|
||||||
|
\node[main] (2) [right of=1] {$belt_1$};
|
||||||
|
\node[main] (3) [right of=2] {$consumer_1$};
|
||||||
|
|
||||||
|
\draw[->] (1) edge node{$p_1$} (2);
|
||||||
|
\draw[->] (2) edge node{$p_2$} (3);
|
||||||
|
|
||||||
|
\end{tikzpicture}
|
||||||
|
\caption{Example of a simple factory}
|
||||||
|
\label{SimpleFactory}
|
||||||
|
\end{figure}
|
||||||
|
|
||||||
|
\section{Constraints}
|
||||||
|
The first step of the factory solving process is the constraint generation.
|
||||||
|
We currently use 3 different types of constraints (Figure \ref{Constraints}).
|
||||||
|
Let's take them one step at a time. The first two constrains (
|
||||||
|
$p_k(t) <_{\Leftarrow} f(t)$ and $p_k(t) <_{\Rightarrow} f(t)$
|
||||||
|
) are pretty similar, both limiting the flow through a port.
|
||||||
|
|
||||||
|
\begin{figure}[ht]
|
||||||
|
|
||||||
|
\begin{equation}
|
||||||
|
\begin{split}
|
||||||
|
Constraints\quad C_k\ &::=\; p_k(t) <_{\Leftarrow} f(t) \\
|
||||||
|
&\quad|\quad p_k(t) <_{\Rightarrow} f(t) \\
|
||||||
|
&\quad|\quad p_1(t) = p_2(f(t))
|
||||||
|
\end{split}
|
||||||
|
\end{equation}
|
||||||
|
\caption{Constraints}
|
||||||
|
\label{Constraints}
|
||||||
|
\end{figure}
|
||||||
|
|
||||||
|
\end{document}
|
|
@ -6,7 +6,7 @@ import Data.Array (length, mapWithIndex)
|
||||||
import Data.Array as Array
|
import Data.Array as Array
|
||||||
import Data.Either (Either)
|
import Data.Either (Either)
|
||||||
import Data.Foldable (foldMap, for_, minimum)
|
import Data.Foldable (foldMap, for_, minimum)
|
||||||
import Data.FoldableWithIndex (forWithIndex_)
|
import Data.FoldableWithIndex (foldlWithIndex, forWithIndex_)
|
||||||
import Data.Generic.Rep (class Generic)
|
import Data.Generic.Rep (class Generic)
|
||||||
import Data.HashMap (HashMap)
|
import Data.HashMap (HashMap)
|
||||||
import Data.HashMap as HashMap
|
import Data.HashMap as HashMap
|
||||||
|
@ -16,12 +16,11 @@ import Data.Int (toNumber)
|
||||||
import Data.Lens (Lens')
|
import Data.Lens (Lens')
|
||||||
import Data.Lens.Record (prop)
|
import Data.Lens.Record (prop)
|
||||||
import Data.List (List(..), (:))
|
import Data.List (List(..), (:))
|
||||||
import Data.List as List
|
|
||||||
import Data.Maybe (Maybe(..), fromJust, fromMaybe)
|
import Data.Maybe (Maybe(..), fromJust, fromMaybe)
|
||||||
import Data.Number (infinity)
|
import Data.Number (infinity)
|
||||||
import Data.Show.Generic (genericShow)
|
import Data.Show.Generic (genericShow)
|
||||||
import Data.Traversable (for)
|
import Data.Traversable (for)
|
||||||
import Data.Tuple (Tuple(..), fst, uncurry)
|
import Data.Tuple (Tuple(..), fst, snd, uncurry)
|
||||||
import Data.Tuple.Nested (type (/\), (/\))
|
import Data.Tuple.Nested (type (/\), (/\))
|
||||||
import Functorio.Lens (modifyAt)
|
import Functorio.Lens (modifyAt)
|
||||||
import Math (sin)
|
import Math (sin)
|
||||||
|
@ -70,8 +69,8 @@ blueBelt :: BeltConfig
|
||||||
blueBelt = { speed: 45.0, delay: 4.0/8.0 }
|
blueBelt = { speed: 45.0, delay: 4.0/8.0 }
|
||||||
|
|
||||||
-- | Example factory
|
-- | Example factory
|
||||||
myFactory :: Factory
|
myFactory1 :: Factory
|
||||||
myFactory = Map.fromArray machines
|
myFactory1 = Map.fromArray machines
|
||||||
where
|
where
|
||||||
machines = mapWithIndex Tuple
|
machines = mapWithIndex Tuple
|
||||||
[ Provider [0, 1] $ startsAtZero $ \t -> 40.0 + 10.0 * sin t
|
[ Provider [0, 1] $ startsAtZero $ \t -> 40.0 + 10.0 * sin t
|
||||||
|
@ -82,6 +81,19 @@ myFactory = Map.fromArray machines
|
||||||
, Consumer 4
|
, Consumer 4
|
||||||
]
|
]
|
||||||
|
|
||||||
|
myFactory :: Factory
|
||||||
|
myFactory = Map.fromArray machines
|
||||||
|
where
|
||||||
|
machines = mapWithIndex Tuple
|
||||||
|
[ Provider [0, 1, 2] $ startsAtZero $ \t -> 80.0
|
||||||
|
, Belt { input: 0, output: 3, config: yellowBelt }
|
||||||
|
, Belt { input: 1, output: 4, config: redBelt }
|
||||||
|
, Belt { input: 2, output: 5, config: blueBelt }
|
||||||
|
, Consumer 3
|
||||||
|
, Consumer 4
|
||||||
|
, Consumer 5
|
||||||
|
]
|
||||||
|
|
||||||
---------- Helpers for real functions
|
---------- Helpers for real functions
|
||||||
type Endomorphism a = a -> a
|
type Endomorphism a = a -> a
|
||||||
|
|
||||||
|
@ -190,7 +202,7 @@ tryFindBoundImpl (targetId /\ targetSide) = do
|
||||||
evalExpr expr <*> pure time
|
evalExpr expr <*> pure time
|
||||||
BiRelationship id raw
|
BiRelationship id raw
|
||||||
| Just relationship <- focusBiRelationship (targetId /\ targetSide) raw -> do
|
| Just relationship <- focusBiRelationship (targetId /\ targetSide) raw -> do
|
||||||
f <- once id fail $ tryFindBoundImpl relationship.p2
|
f <- once id fail $ tryFindValueImpl $ fst relationship.p2
|
||||||
f (relationship.p1top2 time)
|
f (relationship.p1top2 time)
|
||||||
_ -> fail
|
_ -> fail
|
||||||
# runReader constraints
|
# runReader constraints
|
||||||
|
@ -225,29 +237,27 @@ collectConstraintsImpl at = case _ of
|
||||||
Provider for amount -> do
|
Provider for amount -> do
|
||||||
forWithIndex_ for \index id -> do
|
forWithIndex_ for \index id -> do
|
||||||
let limit ports time
|
let limit ports time
|
||||||
= outputs ports time
|
= ports
|
||||||
# Array.findMap (\(id' /\ f) -> if id == id' then Just (f time) else Nothing)
|
# map (\port -> port.id /\ port.maxOutput time)
|
||||||
# unsafePartial fromJust -- TODO: error handling
|
# outputs (amount time)
|
||||||
|
# Array.findMap (\(id' /\ f) -> if id == id' then Just f else Nothing)
|
||||||
|
# unsafePartial fromJust
|
||||||
constrain $ Limit (PortDependent for limit) Input id
|
constrain $ Limit (PortDependent for limit) Input id
|
||||||
where
|
where
|
||||||
outputs :: Array PortData -> Number -> Array (PortId /\ RealFunction)
|
outputs :: Number -> Array (PortId /\ Number) -> Array (PortId /\ Number)
|
||||||
outputs ports time
|
outputs total ports
|
||||||
= outputsImpl (length ports) (List.fromFoldable sorted) amount
|
= ports
|
||||||
|
# Array.sortWith snd
|
||||||
|
# foldlWithIndex (\index (past /\ remaining) (id /\ value) -> do
|
||||||
|
let current
|
||||||
|
| lengthLeft <- remaining / toNumber (count - index), value >= lengthLeft = lengthLeft
|
||||||
|
| otherwise = value
|
||||||
|
((id /\ current):past) /\ (remaining - current))
|
||||||
|
(Nil /\ total)
|
||||||
|
# fst
|
||||||
# Array.fromFoldable
|
# Array.fromFoldable
|
||||||
# Array.zipWith (_.id >>> Tuple) sorted
|
|
||||||
where
|
where
|
||||||
sorted :: Array PortData
|
count = length ports
|
||||||
sorted = Array.sortWith (_.maxOutput >>> (#) time) ports
|
|
||||||
|
|
||||||
outputsImpl :: Int -> List PortData -> RealFunction -> List RealFunction
|
|
||||||
outputsImpl 1 (head:Nil) remaining = pure \time -> min (head.maxOutput time) (remaining time)
|
|
||||||
outputsImpl n (head:tail) remaining = current:(outputsImpl (n - 1) tail $ remaining - current)
|
|
||||||
where
|
|
||||||
current time
|
|
||||||
| head.maxOutput time >= (remaining time) / (toNumber n) = (remaining time) / (toNumber n)
|
|
||||||
| otherwise = head.maxOutput time
|
|
||||||
outputsImpl _ _ _ = Nil
|
|
||||||
|
|
||||||
Consumer for -> do
|
Consumer for -> do
|
||||||
constrain $ Limit (Literal infinity) Output for
|
constrain $ Limit (Literal infinity) Output for
|
||||||
Belt { input, output, config } -> do
|
Belt { input, output, config } -> do
|
||||||
|
|
33
purescript/factorio-throughput/src/Utils/Ord.purs
Normal file
33
purescript/factorio-throughput/src/Utils/Ord.purs
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
module Moontorio.Ord.Extra (Side, left, right, OrderedArray, binarySearch) where
|
||||||
|
|
||||||
|
import Prelude
|
||||||
|
|
||||||
|
import Data.Array (length, unsafeIndex)
|
||||||
|
import Data.Maybe (Maybe(..))
|
||||||
|
import Partial.Unsafe (unsafePartial)
|
||||||
|
|
||||||
|
type OrderedArray = Array
|
||||||
|
newtype Side = Side Boolean
|
||||||
|
|
||||||
|
left :: Side
|
||||||
|
left = Side false
|
||||||
|
|
||||||
|
right :: Side
|
||||||
|
right = Side true
|
||||||
|
|
||||||
|
binarySearch :: forall a. (Int -> a -> Side) -> OrderedArray a -> Maybe Int
|
||||||
|
binarySearch f arr = unsafePartial $ findImpl 0 (length arr)
|
||||||
|
where
|
||||||
|
findImpl :: Partial => _
|
||||||
|
findImpl start length | length == 0 = Nothing
|
||||||
|
| length == 1 = Just start
|
||||||
|
| otherwise = do
|
||||||
|
let middle = start + length / 2
|
||||||
|
let element = unsafeIndex arr middle
|
||||||
|
if f middle element == left then
|
||||||
|
findImpl start (middle - start)
|
||||||
|
else
|
||||||
|
findImpl middle (length + start - middle)
|
||||||
|
|
||||||
|
---------- Typeclass instances
|
||||||
|
derive instance eqSide :: Eq Side
|
Loading…
Reference in a new issue