You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/blog/algebraic-api-design.md
+23-23Lines changed: 23 additions & 23 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -10,7 +10,7 @@ In this post we are going to explore the concept of *algebraic API design* which
10
10
11
11
An API in this context describes the types and operations that a module exposes to the user.
12
12
13
-
SameGame is a deterministic single player game with perfect information. It has a game-tree complexity of $10^{82}$. In other words it is extremely hard to solve. Exhaustive search strategies and traditional path finding algorithms do not perform well. Monte Carlo tree search which is based on random sampling on the other hand is a promising approach. We will go into more details on these concepts below.
13
+
SameGame is a deterministic single player game with perfect information. It has a game-tree complexity of @:math10^{82} @:@. In other words it is extremely hard to solve. Exhaustive search strategies and traditional path finding algorithms do not perform well. Monte Carlo tree search which is based on random sampling on the other hand is a promising approach. We will go into more details on these concepts below.
14
14
15
15
But how can we implement this with functional programming? How can we express algorithms that are based on randomness, mutable state, and side effects in a purely functional way?
16
16
@@ -21,21 +21,21 @@ Let's have a quick recap on the definition of algebraic structures and how they
21
21
## Algebraic Structures
22
22
23
23
An algebraic structure consists of:
24
-
24
+
25
25
* One or more *sets*
26
26
* A set of *operators*
27
27
* A collection of *axioms* (which the operators are required to satisfy)
28
28
29
-
A prototypical example of an algebraic structure from mathematics is a group. A concrete example of a group is the set $\mathbb{Z}$ of integers together with the addition operator denoted as $(\mathbb{Z}, +)$ that satisfy the group axioms.
29
+
A prototypical example of an algebraic structure from mathematics is a group. A concrete example of a group is the set @:math\mathbb{Z} @:@ of integers together with the addition operator denoted as @:math() (\mathbb{Z}, +) @:@ that satisfy the group axioms.
30
30
31
31
A group can be defined in an abstract way like this:
32
32
33
-
-*Set* and *operator*: $(G, \circ)$
33
+
-*Set* and *operator*: @:math() (G, \circ) @:@
34
34
-*Axioms*:
35
-
- Closure: $\forall a, b \in G:a \circ b \in G$
36
-
- Associativity: $\forall a, b, c \in G: a \circ (b \circ c) = (a \circ b) \circ c$
37
-
- Identity: $\exists e \in G: \forall a \in G:e \circ a = a = a \circ e$
38
-
- Inverse: $\forall a \in G: \exists b \in G:a \circ b = e = b \circ a$
35
+
- Closure: @:math\forall a, b \in G:a \circ b \in G @:@
36
+
- Associativity: @:math\forall a, b, c \in G: a \circ (b \circ c) = (a \circ b) \circ c @:@
37
+
- Identity: @:math\exists e \in G: \forall a \in G:e \circ a = a = a \circ e @:@
38
+
- Inverse: @:math\forall a \in G: \exists b \in G:a \circ b = e = b \circ a @:@
39
39
40
40
## Programming
41
41
@@ -64,7 +64,7 @@ def semigroupAssociative(x: A, y: A, z: A): IsEq[A] =
We can create a concrete instance of `Group[A]`, e.g. according to $(\mathbb{Z}, +)$:
67
+
We can create a concrete instance of `Group[A]`, e.g. according to @:math() (\mathbb{Z}, +) @:@:
68
68
69
69
```scala
70
70
importcats.Group
@@ -104,7 +104,7 @@ Once we've defined the algebras that model the API of our domain, we can describ
104
104
105
105
Programs are therefore flexible and constrained at the same time. Flexible in the sense that they can be used with any lawful implementation of the given algebra. And constrained because they can only use the operators provided by the algebra to manipulate values of the types that the algebra is expressed with.
106
106
107
-
To give a crude, concrete example, a program $p$ is expressed in terms of the algebra of `Group[A]`. $p$ can only produce a result by using the operators `combine` and `inverse` on given input parameters of type `A`. Those parameters cannot be manipulated in any other way. Which leaves less room for mistakes and leads to correct programs. The caller of $p$ decides which concrete implementation of `Group[A]` they want to provide. Which makes $p$ reusable in multiple different contexts.
107
+
To give a crude, concrete example, a program @:math p @:@ is expressed in terms of the algebra of `Group[A]`. @:math p @:@ can only produce a result by using the operators `combine` and `inverse` on given input parameters of type `A`. Those parameters cannot be manipulated in any other way. Which leaves less room for mistakes and leads to correct programs. The caller of @:math p @:@ decides which concrete implementation of `Group[A]` they want to provide. Which makes @:math p @:@ reusable in multiple different contexts.
108
108
109
109
We could define a program as follows:
110
110
@@ -120,11 +120,11 @@ Let's look at a concrete and self-contained example.
We will write a program that finds solutions for deterministic single player games with a high game-tree complexity like SameGame.
126
126
127
-
SameGame is played on a $15 \times 15$ board initially filled with blocks of 5 colors. The goal of the game is to remove as many blocks from the board as possible while maximising the score. See [https://en.wikipedia.org/wiki/SameGame](https://en.wikipedia.org/wiki/SameGame) for detailed rules. You can play the game at [js-games.de](http://www.js-games.de/eng/games/samegame/lx/play) or [https://samegame.surge.sh](https://samegame.surge.sh).
127
+
SameGame is played on a @:math15 \times 15 @:@ board initially filled with blocks of 5 colors. The goal of the game is to remove as many blocks from the board as possible while maximising the score. See [https://en.wikipedia.org/wiki/SameGame](https://en.wikipedia.org/wiki/SameGame) for detailed rules. You can play the game at [js-games.de](http://www.js-games.de/eng/games/samegame/lx/play) or [https://samegame.surge.sh](https://samegame.surge.sh).
128
128
129
129
SameGame is a game with perfect information that is very difficult to solve. Given an initial starting position, we can construct a complete game-tree for SameGame as follows:
130
130
@@ -134,7 +134,7 @@ SameGame is a game with perfect information that is very difficult to solve. Giv
134
134
- The root node represents the starting position
135
135
- The leafs are terminal game states
136
136
137
-
The total number of leafs is the game-tree complexity. The game-tree complexity of Tic-Tac-Toe e.g. is about $10^5$. Tic-Tac-Toe is easy to solve by doing an exhaustive search. Whereas SameGame has a complexity of approximately $10^{82}$. This makes it impossible to solve with a brute-force approach or other traditional algorithms in a reasonable amount of time. Smaller SameGame boards are relatively easy to solve. As the size of the board increases we observe a *combinatorial explosion*. The time required to find the best solution increases so rapidly that we hit a solvability limit.
137
+
The total number of leafs is the game-tree complexity. The game-tree complexity of Tic-Tac-Toe e.g. is about @:math10^5 @:@. Tic-Tac-Toe is easy to solve by doing an exhaustive search. Whereas SameGame has a complexity of approximately @:math10^{82} @:@. This makes it impossible to solve with a brute-force approach or other traditional algorithms in a reasonable amount of time. Smaller SameGame boards are relatively easy to solve. As the size of the board increases we observe a *combinatorial explosion*. The time required to find the best solution increases so rapidly that we hit a solvability limit.
138
138
139
139
## Monte Carlo tree search
140
140
@@ -144,12 +144,12 @@ A stochastic optimization algorithm that has successfully been employed to game
144
144
145
145
Here is a very simple version of a Monte Carlo tree search:
146
146
147
-
1. Choose the root node as the current node $n$ of the game-tree
148
-
2. For the current node $n$, determine all legal moves $ms$
147
+
1. Choose the root node as the current node @:math n @:@ of the game-tree
148
+
2. For the current node @:math n @:@, determine all legal moves @:math ms @:@
149
149
- If no legal moves exist, the algorithm terminates
150
-
3. Determine all child nodes $cs$ of $n$ by applying each of the moves $ms$ to the current state $n$
151
-
4. Perform a random simulation for each of the child nodes $cs$
152
-
5. From the child nodes $cs$ choose the node with the best simulation result, and continue with step 2.
150
+
3. Determine all child nodes @:math cs @:@ of @:math n @:@ by applying each of the moves @:math ms @:@ to the current state @:math n @:@
151
+
4. Perform a random simulation for each of the child nodes @:math cs @:@
152
+
5. From the child nodes @:math cs @:@ choose the node with the best simulation result, and continue with step 2.
153
153
154
154
A way to improve on this basic algorithm is to add a nested (lower level) search at step 4. such that a random simulation is performed if the current level equals 1, otherwise a `level - 1` search is performed.
@@ -468,7 +468,7 @@ Of course, there are additional test strategies that can be employed. In particu
468
468
469
469
## Application
470
470
471
-
With `cats.effect.IOApp` we describe a purely functional program that performs a Monte Carlo tree search for a given initial board position. For demonstration purposes we use a smaller board of size $6 \times 6$ to shorten the search time.
471
+
With `cats.effect.IOApp` we describe a purely functional program that performs a Monte Carlo tree search for a given initial board position. For demonstration purposes we use a smaller board of size @:math6 \times 6 @:@ to shorten the search time.
The Monte Carlo tree search algorithm presented in this post has been intentionally kept simple. There are numerous different strategies of how to guide the tree search based on heuristics to influence the choice of moves which require multiple parameters that have to be fine tuned to maximize the outcomes.
0 commit comments