diff --git a/README.md b/README.md index 860b204..6eadd2f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Cellular-Automata 🔬 +# Cellular Automata 🔬 [![celebi-pkg](https://circleci.com/gh/kcelebi/cellular-automata.svg?style=svg)](https://circleci.com/gh/kcelebi/cellular-automata) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) @@ -12,11 +12,62 @@ This purpose of this project is to test different research ideas for cellular au ## How to Use -### Repo Structure +You can utilize these functions and programs by cloning/forking this repository. Depending on future development, the structure of this project might change into a Python package available on PyPI. +Clone/fork the repository to your local. Obtain the requirements: + + python -m pip install -r requirements.txt + +Each stage of an automata simulation involves a `state`. You need to be able to initialize a state, update it, and view/analyze it. To initialize a state, either generate a random one or input it manually (as a 2d numpy or vanilla Python array): + + import src.sim.automata as atm # contains functions to affect states + import src.sim.stats as stats # contains functions to analyze states + import src.sim.analys as ans # contains functions to analyze states + from src.sim.rules import Rules # contains the different rule-sets + + state = atm.get_random_state(shape = (5, 4)) # generates a 5 x 4 frame + + new_state = atm.update(state, rule = Rules.CONWAY) # updates using Conway's Game of Life rules + + ans.plot_state(new_state) # returns plt.imshow() of the provided state + ans.display_state(new_state) # prints the state to CLI as ASCII + + num_alive = stats.get_total_alive(new_state) # get the total alive + +You can also play through multiple steps which are outputted as a 3D numpy array. Let's play through 15 steps: + + states = ans.play(state, steps = 15, rules = Rules.CONWAY) + print(states.shape) # outputs: (15, 5, 4) + +Want to analyze this simulation? + + survival_stats = ans.get_survival_stats(states) + + plt.plot(survival_stats / (state.shape[0] * state.shape[1])) + plt.title('Survival Rate') + plt.xlabel('Time') + plt.ylabel('Pct Alive') + plt.show() + +If you want to design your own rules, you can contribute to the `rules.py` module or write a custom function to pass through to `atm.update()` or `ans.play()`. The provided rule-set is to be applied to each cell in the grid and considers the value of eligible neighbors and itself. As a lambda, your function should be of the form: + + my_rule = lambda neighbors, curr_cell, state: ... # your calculation + +### Module Structure + +Hierarchy of calls/imports: + +- automata.py + - rules.py + - sim.py + - stats.py + - analysis.py + ## Contributing +Please feel free to fork and submit a PR. For other queries, I can be reached at my email: kayacelebi17@gmail.com + ## Release Notes * Conway's Game of Life Interactive diff --git a/nb/automata-analysis-v0.ipynb b/nb/automata-analysis-v0.ipynb index e451de3..638c465 100644 --- a/nb/automata-analysis-v0.ipynb +++ b/nb/automata-analysis-v0.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "markdown", - "id": "df406f50", + "id": "6d13da26", "metadata": {}, "source": [ "*This notebook is my own notes / development playground. It will be disorganized in nature. Feel free to skim through.*" @@ -45,7 +45,7 @@ { "cell_type": "code", "execution_count": 24, - "id": "50a54b48", + "id": "6f4c7b39", "metadata": {}, "outputs": [ { @@ -98,7 +98,7 @@ }, { "cell_type": "markdown", - "id": "2cf55a8a", + "id": "85bae9cf", "metadata": {}, "source": [ "### Cycle Detection\n", @@ -136,7 +136,7 @@ { "cell_type": "code", "execution_count": 24, - "id": "5cdf66b1", + "id": "615b1ade", "metadata": {}, "outputs": [], "source": [ @@ -147,7 +147,7 @@ { "cell_type": "code", "execution_count": 41, - "id": "5e6fa5b4", + "id": "765a7122", "metadata": {}, "outputs": [ { @@ -171,7 +171,7 @@ { "cell_type": "code", "execution_count": 27, - "id": "f3cd690c", + "id": "282d1836", "metadata": {}, "outputs": [ { @@ -193,7 +193,7 @@ { "cell_type": "code", "execution_count": 28, - "id": "80f43b73", + "id": "b6bd8818", "metadata": {}, "outputs": [ { @@ -215,7 +215,7 @@ { "cell_type": "code", "execution_count": 7, - "id": "159388c7", + "id": "8fc3a363", "metadata": {}, "outputs": [ { @@ -241,7 +241,7 @@ { "cell_type": "code", "execution_count": 13, - "id": "0212826a", + "id": "cfa03711", "metadata": {}, "outputs": [ { @@ -266,7 +266,7 @@ { "cell_type": "code", "execution_count": 24, - "id": "fb5eadd6", + "id": "1a71c907", "metadata": {}, "outputs": [ { @@ -294,7 +294,7 @@ { "cell_type": "code", "execution_count": 22, - "id": "7431a6bf", + "id": "47b21960", "metadata": {}, "outputs": [ { @@ -329,7 +329,7 @@ }, { "cell_type": "markdown", - "id": "12fcf5e0", + "id": "15cfba73", "metadata": {}, "source": [ "### Testing Rule Integration" @@ -338,7 +338,7 @@ { "cell_type": "code", "execution_count": 2, - "id": "5ca955c4", + "id": "b2ee2e99", "metadata": {}, "outputs": [ { @@ -357,34 +357,10 @@ "state" ] }, - { - "cell_type": "code", - "execution_count": 16, - "id": "18b63b0d", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "plt.imshow(~state, cmap = 'gray')\n", - "plt.show()" - ] - }, { "cell_type": "code", "execution_count": 3, - "id": "3ccd93ea", + "id": "be5c2199", "metadata": {}, "outputs": [ { @@ -418,68 +394,298 @@ }, { "cell_type": "code", - "execution_count": 4, - "id": "50999995", + "execution_count": 9, + "id": "21f9d915", + "metadata": {}, + "outputs": [], + "source": [ + "state = atm.get_random_state((5, 5))\n", + "out = ans.play(state, steps = 10, rule = Rules.CONWAY)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "ae73a168", + "metadata": {}, + "outputs": [ + { + "ename": "ValueError", + "evalue": "too many values to unpack (expected 2)", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m/var/folders/cc/c6pxrx8n6wx77yf6_g8dvdw40000gn/T/ipykernel_6145/48032009.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mans\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_alive_matrix\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mout\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m~/Projects/research/cellular-automata/src/analysis.py\u001b[0m in \u001b[0;36mget_alive_matrix\u001b[0;34m(state)\u001b[0m\n\u001b[1;32m 29\u001b[0m \u001b[0mstate\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0matm\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstate_fix\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mstate\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 30\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 31\u001b[0;31m \u001b[0mx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0my\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mstate\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mshape\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 32\u001b[0m \u001b[0malive_mat\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mzeros\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mstate\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mshape\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdtype\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mint\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 33\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mi\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mValueError\u001b[0m: too many values to unpack (expected 2)" + ] + } + ], + "source": [ + "ans.get_alive_matrix(out)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "dd3b7c8c", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "array([[[0, 0, 0, 1, 0, 0, 0]],\n", - "\n", - " [[0, 0, 1, 1, 1, 0, 0]],\n", - "\n", - " [[0, 1, 1, 0, 0, 1, 0]],\n", - "\n", - " [[1, 1, 0, 1, 1, 1, 1]],\n", - "\n", - " [[1, 0, 0, 1, 0, 0, 1]],\n", - "\n", - " [[1, 1, 1, 1, 1, 1, 1]],\n", - "\n", - " [[1, 0, 0, 0, 0, 0, 1]],\n", - "\n", - " [[1, 1, 0, 0, 0, 1, 1]],\n", - "\n", - " [[1, 0, 1, 0, 1, 1, 1]],\n", - "\n", - " [[1, 0, 1, 0, 1, 0, 1]]])" + "array([[1, 0, 0, 1, 1],\n", + " [0, 1, 1, 0, 0],\n", + " [0, 0, 1, 1, 1],\n", + " [0, 1, 0, 1, 1],\n", + " [0, 1, 0, 0, 0]])" ] }, - "execution_count": 4, + "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "out" + "out[0]" ] }, { "cell_type": "code", - "execution_count": 34, - "id": "9fa22e77", + "execution_count": 26, + "id": "481183f3", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "(8, 2)" + "array([[1, 0],\n", + " [0, 1],\n", + " [1, 1]])" ] }, - "execution_count": 34, + "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "atm.get_neighbors(1, 1, (3,3)).shape" + "atm.get_neighbors(0, 0, (5,5))" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "6564f077", + "metadata": {}, + "outputs": [], + "source": [ + "f = np.vectorize(ans.get_alive_matrix)" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "id": "8f809a1e", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[1, 3, 3, 2, 1],\n", + " [2, 3, 4, 6, 4],\n", + " [2, 4, 5, 5, 3],\n", + " [2, 2, 5, 4, 3],\n", + " [2, 1, 3, 2, 2]])" + ] + }, + "execution_count": 39, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ans.get_alive_matrix(out[0])" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "id": "91d3e52f", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[2, 2, 3, 1, 1],\n", + " [2, 2, 4, 3, 2],\n", + " [2, 2, 2, 2, 1],\n", + " [1, 1, 2, 3, 1],\n", + " [1, 2, 1, 2, 1]])" + ] + }, + "execution_count": 40, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ans.get_alive_matrix(out[1])" + ] + }, + { + "cell_type": "code", + "execution_count": 72, + "id": "edece9a0", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "2.25" + ] + }, + "execution_count": 72, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "am = ans.get_alive_matrix(out[0])\n", + "am[0:2, 0:2].mean()" + ] + }, + { + "cell_type": "code", + "execution_count": 77, + "id": "6bbde2aa", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[1, 3, 3, 2, 1],\n", + " [2, 3, 4, 6, 4],\n", + " [2, 4, 5, 5, 3],\n", + " [2, 2, 5, 4, 3],\n", + " [2, 1, 3, 2, 2]])" + ] + }, + "execution_count": 77, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "am" + ] + }, + { + "cell_type": "code", + "execution_count": 79, + "id": "e2cde96c", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[1, 3, 3, 2, 1],\n", + " [2, 4, 5, 6, 4]])" + ] + }, + "execution_count": 79, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "np.maximum.reduceat(am, [0, 1])" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "id": "3b58c967", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.imshow(np.cov(out[0].reshape(-1), out[1].reshape(-1)), cmap = 'gray')\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "id": "d7a778ae", + "metadata": {}, + "outputs": [], + "source": [ + "cov = np.array([np.cov(out[i], out[i+1]).reshape(-1) for i in range(out.shape[0]-1)])" + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "id": "745885f1", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(9, 100)" + ] + }, + "execution_count": 55, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "cov.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 57, + "id": "76365ec8", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.plot(cov)\n", + "plt.show()" ] }, { "cell_type": "code", "execution_count": null, - "id": "16cb1496", + "id": "13ecc371", "metadata": {}, "outputs": [], "source": [] diff --git a/sim b/sim new file mode 100644 index 0000000..7af8dfd --- /dev/null +++ b/sim @@ -0,0 +1,76 @@ +import numpy as np + +''' + Automata is state by state + Note: might be better to do this in C for speedup + + idea -- create reinforcement learning model + - we have state, action + - model learns to add points to the CA state to achieve some outcome + - consider: ask agent to create a certain state, or some qualification using k moves + - how does it do it + + - we need pattern detection + - we need cycle detection + - can we transform each image to a graph... + - each state to a graph? + + - some web server where you can pkay / analyze differnet automata setup + - have the interactive code etc + - need to port it all to JS +''' + + + +''' + Brute force update -- O(n^2) + + NOTE: this is *not* updating in-place +''' +def update(state, rule): + state = state_fix(state) + + x, y = state.shape + new_state = np.zeros(state.shape, dtype = int) + + for i in range(x): + for j in range(y): + neighbors = get_neighbors(i, j, shape = state.shape) + new_state[i, j] = rule(neighbors, cell = state[i, j], state = state) + + return new_state + +def np_update(state): + x, y = state.shape + new_state = np.zeros(state.shape) + + # write a lambda to generate the update more efficiently + return + +''' + Returns all valid neighbors +''' +def get_neighbors(i, j, shape): + # list comp generates all neighbors including center. If center or invalid neighbor, + # does i-10, j-10 as coord to remove in next step + neighbors = np.reshape([[[i + u, j + v] if in_range(i + u, j + v, shape = shape) else [i - 10, j - 10] for u in [-1, 0, 1]] for v in [-1, 0, 1]], (-1, 2)) + return neighbors[~np.all(np.logical_or(neighbors == [i, j], neighbors == [i - 10, j - 10]), axis = 1)] # make sure to exlude center and not in-range values + +''' + Check the provided coord is in range of the matrix +''' +def in_range(i, j, shape): + if i < shape[0] and i > -1 and j > -1 and j < shape[1]: + return True + return False + +def get_random_state(shape): + return np.random.randint(0, 2, size = shape) + +def state_fix(state): + if type(state) != np.array: + state = np.array(state, dtype = int) + if len(state.shape) == 1: + state = state.reshape((1, -1)) + + return state \ No newline at end of file diff --git a/src/analysis.py b/src/analysis.py deleted file mode 100644 index 64e78f7..0000000 --- a/src/analysis.py +++ /dev/null @@ -1,98 +0,0 @@ -import numpy as np -import automata as atm -from rules import Rules - -def get_total_alive(state): - state = state_fix(state) - return (state == 1).sum() - -def get_total_dead(state): - state = state_fix(state) - return (state == 0).sum() - -def is_terminal_state(state): - state = state_fix(state) - return get_total_alive(state) == 0 - -# ------------------------------ - -def get_survival_stats(states): - state = state_fix(state) - return np.array([get_total_alive(state) for state in states], dtype = int) - -# each cell represents how many alive neighbors it has -''' - O(8n^2)... whatever -''' -def get_alive_matrix(state): - state = state_fix(state) - - x, y = state.shape - alive_mat = np.zeros(state.shape) - for i in range(x): - for j in range(y): - for neighbor_i, neighbor_j in atm.get_neighbors(i, j, shape = state.shape): - alive_mat[i, j] += state[neighbor_i, neighbor_j] - - - return alive_mat -# ------------------------------ - -def get_random_state(shape): - return np.random.randint(0, 2, size = shape) - -# ------------------------------ VERBOSE FUNCTIONS - -''' - Print the states out in ASCII form to command line -''' -def display_state(state): - x, y = state.shape - - finstr = "" - for i in range(x): - finstr += '|' - for j in range(y): - if state[i, j] == 1: - finstr += "██" - else: - finstr += " " - finstr += ("|\n" + '--'*state.shape[1]*2) - print(finstr) - -''' - Use matplotlib to plot a state, works for 1D as well -''' -def plot_state(state): - state = state_fix(state) - - fig, axs = plt.subplots() - if state.shape[0] > 1: - axs.imshow(~state[0], cmap = 'gray') - else: - axs.imshow(~state, cmap = 'gray') - - axs.set_xticks(np.arange(len(state))+0.5) - axs.set_yticks(np.arange(len(state))+0.5) - axs.set_xticklabels([]) - axs.set_yticklabels([]) - axs.grid() - plt.show() - -# ------------------------------ - -def play(state, steps, rule = Rules.CONWAY, verbose = False, verbose_func = display_state): - state = state_fix(state) - - i = 1 - states = np.zeros((steps, *state.shape), dtype = int) - states[0, :, :] = state - while i < steps and not is_terminal_state(state): - if verbose: - verbose_func(state) - - state = atm.update(state, rule = rule) - states[i, :, :] = state - i += 1 - - return states diff --git a/src/analysis/analysis.py b/src/analysis/analysis.py new file mode 100644 index 0000000..45a2237 --- /dev/null +++ b/src/analysis/analysis.py @@ -0,0 +1,48 @@ +import numpy as np + +import sys +sys.path.append('../') + +import sim.automata as atm +from sim.rules import Rules + + + +# ------------------------------ VERBOSE FUNCTIONS + +''' + Print the states out in ASCII form to command line +''' +def display_state(state): + x, y = state.shape + + finstr = "" + for i in range(x): + finstr += '|' + for j in range(y): + if state[i, j] == 1: + finstr += "██" + else: + finstr += " " + finstr += ("|\n") + print(finstr + '--'*state.shape[1]*2) + +''' + Use matplotlib to plot a state, works for 1D as well +''' +def plot_state(state): + state = atm.state_fix(state) + + fig, axs = plt.subplots() + if state.shape[0] > 1: + axs.imshow(~state[0], cmap = 'gray') + else: + axs.imshow(~state, cmap = 'gray') + + axs.set_xticks(np.arange(len(state))+0.5) + axs.set_yticks(np.arange(len(state))+0.5) + axs.set_xticklabels([]) + axs.set_yticklabels([]) + axs.grid() + plt.show() + diff --git a/src/analysis/feature_extract.py b/src/analysis/feature_extract.py new file mode 100644 index 0000000..d574d64 --- /dev/null +++ b/src/analysis/feature_extract.py @@ -0,0 +1,8 @@ +import numpy as np + +import sys +sys.path.append('../') + +import sim.automata as atm +from sim.rules import Rules + diff --git a/src/analysis/stats.py b/src/analysis/stats.py new file mode 100644 index 0000000..e16914c --- /dev/null +++ b/src/analysis/stats.py @@ -0,0 +1,44 @@ +import numpy as np + +import sys +sys.path.append('../') + +import sim.automata as atm +from sim.rules import Rules + +# ------------------------------ STATS + +def get_total_alive(state): + state = atm.state_fix(state) + return (state == 1).sum() + +def get_total_dead(state): + state = atm.state_fix(state) + return (state == 0).sum() + +def is_terminal_state(state): + state = atm.state_fix(state) + return get_total_alive(state) == 0 + +# ------------------------------ STAT MATRICES + +def get_survival_stats(states): + return np.array([get_total_alive(state) for state in states], dtype = int) + +# each cell represents how many alive neighbors it has +''' + O(8n^2)... whatever +''' +def get_alive_matrix(state): + state = atm.state_fix(state) + + x, y = state.shape + alive_mat = np.zeros(state.shape, dtype = int) + for i in range(x): + for j in range(y): + # counts how many neighbors are alive (does not include self) + for neighbor_i, neighbor_j in atm.get_neighbors(i, j, shape = state.shape): + alive_mat[i, j] += state[neighbor_i, neighbor_j] + + + return alive_mat \ No newline at end of file diff --git a/src/machine_learning/learning_agents.py b/src/machine_learning/learning_agents.py new file mode 100644 index 0000000..09a50f8 --- /dev/null +++ b/src/machine_learning/learning_agents.py @@ -0,0 +1,99 @@ +import sys +sys.path.append('../') + +from path_handler import PathHandler as PH +import sim.automata as atm +from sim.rules import Rules + + +__all__ = ['ReinforcementAgent'] + +class Agent: + + def __init__(self, index = 0): + self.index = index + + def get_action(self, state): + raise NotImplementedError() + + +class ValueEstimationAgent(Agent): + + """ + Abstract agent which assigns values to (state,action) + Q-Values for an environment. As well as a value to a + state and a policy given respectively by, + + V(s) = max_{a in actions} Q(s,a) + policy(s) = arg_max_{a in actions} Q(s,a) + + Both ValueIterationAgent and QLearningAgent inherit + from this agent. While a ValueIterationAgent has + a model of the environment via a MarkovDecisionProcess + (see mdp.py) that is used to estimate Q-Values before + ever actually acting, the QLearningAgent estimates + Q-Values while acting in the environment. + """ + + def __init__(self, alpha, epsilon, gamma, num_training): + ''' + alpha - learning rate + epsilon - exploration rate + gamma - discount factor + num_training - number of training episodes, i.e. no learning after these many episodes + ''' + self.alpha = alpha + self.epsilon = epsilon + self.gamma = gamma + self.num_training = num_training + + def get_Q_value(self, state, action): + raise NotImplementedError() + + def get_value(self, state): + raise NotImplementedError() + + def get_policy(self, state): + raise NotImplementedError() + + def get_action(self, state): + raise NotImplementedError() + +class ReinforcementAgent(ValueEstimationAgent): + + def update(self, state, action, next_state, reward): + raise NotImplementedError() + + def get_legal_actions(self, state): + return self.action_func(state) + + def observe_transition(self, state, action, next_state, delta_reward): + self.episode_rewards += delta_reward + self.update(state, action, next_state, delta_reward) + + def start_episode(self): + ... + + def stop_episode(self): + ... + + def __init__(self, action_func = None, num_training = 100, epsilon = 0.5, alpha = 0.5, gamma = 1): + # we should never be in this position, overwrite this later + if action_func is None: + action_func = lambda state: state.get_legal_actions() # not possible, state not an obj + + self.action_func = action_func + self.episodes_so_far = 0 + self.accum_train_rewards = 0.0 + self.accum_train_rewards = 0.0 + self.num_training = int(num_training) + self.epsilon = float(epsilon) + self.alpha = float(alpha) + self.discount = float(gamma) + + + + + + + diff --git a/src/machine_learning/q_learning_agents.py b/src/machine_learning/q_learning_agents.py new file mode 100644 index 0000000..480da05 --- /dev/null +++ b/src/machine_learning/q_learning_agents.py @@ -0,0 +1,70 @@ +import random + +import sys +sys.path.append('../') + +from machine_learning.learning_agents import * +from path_handler import PathHandler as PH +import sim.automata as atm +from sim.rules import Rules + + +class QLearningAgent(ReinforcementAgent): + + def __init__(self, **args): + ReinforcementAgent.__init__(self, **args) + + self.q_values = util.Counter()? + + + def get_Q_value(self, state, action): + """ + Returns Q(state,action) + Should return 0.0 if we have never seen a state + or the Q node value otherwise + """ + return self.q_values[(state, action)] + + def compute_value_from_Q_values(self, state): + """ + Returns max_action Q(state,action) + where the max is over legal actions. Note that if + there are no legal actions, which is the case at the + terminal state, you should return a value of 0.0. + """ + + legal_actions = self.get_legal_actions(state) + + #Terminal + if len(legal_actions) == 0: + return 0.0 + + return max([self.getQValue(state, a) for a in legal_actions]) + + + def compute_action_from_Q_values(self, state): + """ + Compute the best action to take in a state. Note that if there + are no legal actions, which is the case at the terminal state, + you should return None. + """ + legal_actions = self.get_legal_actions(state) + + # Terminal + if len(legal_actions) == 0: + return None + + best = sorted([(a, self.get_Q_value(state, a)) for a in legal_actions], key = lambda x: x[1], reverse = True) + return random.choice([b[0] for b in best if b[1] == best[0][1]]) + + def get_action(self, state): + legal_actions = self.get_legal_actions(state) + + # Terminal state + if len(legal_actions) == 0: + return None + + if random.random() < self.epsilon: + return random.choice(legal_actions) + return self.compute_action_from_Q_values(state) + diff --git a/src/path_handler.py b/src/path_handler.py index 7f7c83a..a01bd76 100644 --- a/src/path_handler.py +++ b/src/path_handler.py @@ -4,10 +4,19 @@ class PathHandler(Enum): SRC_ROOT = Path(__file__) + + ML = SRC_ROOT / 'machine_learning' + ANALYSIS = SRC_ROOT / 'analysis' + SIM = SRC_ROOT / 'sim' + + + # ------ + TESTS = SRC_ROOT.parent / 'tests' VIZ = SRC_ROOT.parent / 'visualize' DATA = SRC_ROOT.parent / 'data' + def __truediv__(self, other): return self / (+other if type(other) is PathHandler else other) diff --git a/src/automata.py b/src/sim/automata.py similarity index 96% rename from src/automata.py rename to src/sim/automata.py index 83787b8..7af8dfd 100644 --- a/src/automata.py +++ b/src/sim/automata.py @@ -64,6 +64,9 @@ def in_range(i, j, shape): return True return False +def get_random_state(shape): + return np.random.randint(0, 2, size = shape) + def state_fix(state): if type(state) != np.array: state = np.array(state, dtype = int) diff --git a/src/rules.py b/src/sim/rules.py similarity index 94% rename from src/rules.py rename to src/sim/rules.py index c93607d..ebdd202 100644 --- a/src/rules.py +++ b/src/sim/rules.py @@ -1,5 +1,9 @@ from enum import Enum -import automata as atm + +import sys +sys.path.append('../') + +import sim.automata as atm # instead of just conway's, define a # lambda for arbitrary rule sets diff --git a/src/sim/sim.py b/src/sim/sim.py new file mode 100644 index 0000000..a6525a9 --- /dev/null +++ b/src/sim/sim.py @@ -0,0 +1,26 @@ +import numpy as np + +import sys +sys.path.append('../') + +import sim.automata as atm +from sim.rules import Rules + +''' + Play through multiple states. Can apply custom rule set and verbosity function. +''' +def play(state, steps, rule = Rules.CONWAY, verbose = False, verbose_func = display_state): + state = atm.state_fix(state) + + i = 1 + states = np.zeros((steps, *state.shape), dtype = int) + states[0, :, :] = state + while i < steps and not is_terminal_state(state): + if verbose: + verbose_func(state) + + state = atm.update(state, rule = rule) + states[i, :, :] = state + i += 1 + + return states diff --git a/tests/test_class.py b/tests/test_class.py index f69eaf5..59f1427 100644 --- a/tests/test_class.py +++ b/tests/test_class.py @@ -5,14 +5,13 @@ sys.path.append('../src') from path_handler import PathHandler as PH -import automata as atm -import analysis as ans -from rules import Rules +import sim.automata as atm +import analysis.stats as stats +from sim.rules import Rules def test_tautology(): assert 1 == 1 - # ------------------------------ AUTOMATA.PY def test_in_range_0():