| { |
| "cells": [ |
| { |
| "cell_type": "markdown", |
| "id": "49dab42f", |
| "metadata": {}, |
| "source": [ |
| "# Counter\n", |
| "\n", |
| "Let's build a simple counter using Burr. When the counter terminates, print the count and the current time." |
| ] |
| }, |
| { |
| "cell_type": "markdown", |
| "id": "84328dc0", |
| "metadata": {}, |
| "source": [ |
| "## Imports" |
| ] |
| }, |
| { |
| "cell_type": "code", |
| "execution_count": 1, |
| "id": "initial_id", |
| "metadata": { |
| "ExecuteTime": { |
| "end_time": "2024-03-27T00:11:36.093767Z", |
| "start_time": "2024-03-27T00:11:36.088301Z" |
| }, |
| "collapsed": true, |
| "jupyter": { |
| "outputs_hidden": true |
| } |
| }, |
| "outputs": [], |
| "source": [ |
| "import datetime\n", |
| "\n", |
| "from burr.core import action, State, ApplicationBuilder, expr" |
| ] |
| }, |
| { |
| "cell_type": "markdown", |
| "id": "396c5e0c", |
| "metadata": {}, |
| "source": [ |
| "## Define actions\n", |
| "We define the function `increment()` that has a `State` as input and outputs a new `State`. The decorator `@action` specifies it's a Burr action and it will need to read and write from the `counter` attribute in `State`. " |
| ] |
| }, |
| { |
| "cell_type": "code", |
| "execution_count": 2, |
| "id": "64c67b15363653e9", |
| "metadata": { |
| "ExecuteTime": { |
| "end_time": "2024-03-27T00:11:36.548223Z", |
| "start_time": "2024-03-27T00:11:36.539358Z" |
| }, |
| "collapsed": false, |
| "jupyter": { |
| "outputs_hidden": false |
| } |
| }, |
| "outputs": [], |
| "source": [ |
| "@action(reads=[\"counter\"], writes=[\"counter\"])\n", |
| "def increment(state: State) -> State:\n", |
| " \"\"\"Increment the counter by 1\"\"\"\n", |
| " \n", |
| " # get the value from the `state`\n", |
| " current_count = state[\"counter\"]\n", |
| " current_count += 1\n", |
| "\n", |
| " print(\"Count: \", current_count)\n", |
| "\n", |
| " # use `.update()` to create a new `State`\n", |
| " return state.update(counter=current_count)\n", |
| "\n", |
| "\n", |
| "@action(reads=[\"counter\"], writes=[])\n", |
| "def exit_counter(state: State) -> State:\n", |
| " \"\"\"Print the current count and the current time\"\"\"\n", |
| " current_count = state[\"counter\"]\n", |
| "\n", |
| " print(f\"Finished counting to {current_count} at {datetime.datetime.now():%H:%M:%S %Y-%m-%d}\")\n", |
| "\n", |
| " return state" |
| ] |
| }, |
| { |
| "cell_type": "markdown", |
| "id": "197106df", |
| "metadata": {}, |
| "source": [ |
| "## Build the `Application`\n", |
| "We pass the action to the `ApplicationBuilder` via `.with_actions()`. Then, we specify the valid transitions between actions: `increment -> increment` and `increment -> exit_counter`. The `expr`ession construct specifies to use the transition `increment -> increment` whenever the `counter` value in state is under ten. Then, default to `increment -> exit_counter` to terminate the application. We also use `.with_entrypoint()` to define where to start and `.with_state()` to set the starting state value." |
| ] |
| }, |
| { |
| "cell_type": "code", |
| "execution_count": 3, |
| "id": "72ca90a1", |
| "metadata": {}, |
| "outputs": [ |
| { |
| "data": { |
| "image/svg+xml": [ |
| "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n", |
| "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n", |
| " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n", |
| "<!-- Generated by graphviz version 2.43.0 (0)\n", |
| " -->\n", |
| "<!-- Title: %3 Pages: 1 -->\n", |
| "<svg width=\"220pt\" height=\"113pt\"\n", |
| " viewBox=\"0.00 0.00 220.00 113.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n", |
| "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 109)\">\n", |
| "<title>%3</title>\n", |
| "<polygon fill=\"white\" stroke=\"transparent\" points=\"-4,4 -4,-109 216,-109 216,4 -4,4\"/>\n", |
| "<!-- increment -->\n", |
| "<g id=\"node1\" class=\"node\">\n", |
| "<title>increment</title>\n", |
| "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M88,-105C88,-105 20,-105 20,-105 14,-105 8,-99 8,-93 8,-93 8,-80 8,-80 8,-74 14,-68 20,-68 20,-68 88,-68 88,-68 94,-68 100,-74 100,-80 100,-80 100,-93 100,-93 100,-99 94,-105 88,-105\"/>\n", |
| "<text text-anchor=\"middle\" x=\"54\" y=\"-82.8\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">increment</text>\n", |
| "</g>\n", |
| "<!-- increment->increment -->\n", |
| "<g id=\"edge1\" class=\"edge\">\n", |
| "<title>increment->increment</title>\n", |
| "<path fill=\"none\" stroke=\"black\" stroke-dasharray=\"5,2\" d=\"M100.02,-92.72C110.41,-92.16 118,-90.09 118,-86.5 118,-84.26 115.03,-82.61 110.27,-81.55\"/>\n", |
| "<polygon fill=\"black\" stroke=\"black\" points=\"110.38,-78.04 100.02,-80.28 109.52,-84.98 110.38,-78.04\"/>\n", |
| "<text text-anchor=\"middle\" x=\"165\" y=\"-82.8\" font-family=\"Times,serif\" font-size=\"14.00\">counter < 10</text>\n", |
| "</g>\n", |
| "<!-- exit_counter -->\n", |
| "<g id=\"node2\" class=\"node\">\n", |
| "<title>exit_counter</title>\n", |
| "<path fill=\"#b4d8e4\" stroke=\"black\" d=\"M96,-37C96,-37 12,-37 12,-37 6,-37 0,-31 0,-25 0,-25 0,-12 0,-12 0,-6 6,0 12,0 12,0 96,0 96,0 102,0 108,-6 108,-12 108,-12 108,-25 108,-25 108,-31 102,-37 96,-37\"/>\n", |
| "<text text-anchor=\"middle\" x=\"54\" y=\"-14.8\" font-family=\"Helvetica,sans-Serif\" font-size=\"14.00\">exit_counter</text>\n", |
| "</g>\n", |
| "<!-- increment->exit_counter -->\n", |
| "<g id=\"edge2\" class=\"edge\">\n", |
| "<title>increment->exit_counter</title>\n", |
| "<path fill=\"none\" stroke=\"black\" d=\"M54,-67.81C54,-61.6 54,-54.45 54,-47.6\"/>\n", |
| "<polygon fill=\"black\" stroke=\"black\" points=\"57.5,-47.24 54,-37.24 50.5,-47.24 57.5,-47.24\"/>\n", |
| "</g>\n", |
| "</g>\n", |
| "</svg>\n" |
| ], |
| "text/plain": [ |
| "<graphviz.graphs.Digraph at 0x7f2886e3ead0>" |
| ] |
| }, |
| "execution_count": 3, |
| "metadata": {}, |
| "output_type": "execute_result" |
| } |
| ], |
| "source": [ |
| "app = (\n", |
| " ApplicationBuilder()\n", |
| " .with_actions(increment, exit_counter)\n", |
| " .with_transitions(\n", |
| " (\"increment\", \"increment\", expr(\"counter < 10\")),\n", |
| " (\"increment\", \"exit_counter\"),\n", |
| " )\n", |
| " .with_state(counter=0)\n", |
| " .with_entrypoint(\"increment\")\n", |
| " .build()\n", |
| ")\n", |
| "app.visualize(include_conditions=True)" |
| ] |
| }, |
| { |
| "cell_type": "code", |
| "execution_count": 4, |
| "id": "a63802fa10f73ca8", |
| "metadata": { |
| "ExecuteTime": { |
| "end_time": "2024-03-27T00:11:38.483852Z", |
| "start_time": "2024-03-27T00:11:38.463109Z" |
| }, |
| "collapsed": false, |
| "jupyter": { |
| "outputs_hidden": false |
| } |
| }, |
| "outputs": [ |
| { |
| "name": "stdout", |
| "output_type": "stream", |
| "text": [ |
| "Count: 1\n", |
| "Count: 2\n", |
| "Count: 3\n", |
| "Count: 4\n", |
| "Count: 5\n", |
| "Count: 6\n", |
| "Count: 7\n", |
| "Count: 8\n", |
| "Count: 9\n", |
| "Count: 10\n", |
| "Finished counting to 10 at 18:44:29 2024-08-26\n" |
| ] |
| } |
| ], |
| "source": [ |
| "action_obj, result, state = app.run(halt_after=[\"exit_counter\"])" |
| ] |
| } |
| ], |
| "metadata": { |
| "kernelspec": { |
| "display_name": "Python 3 (ipykernel)", |
| "language": "python", |
| "name": "python3" |
| }, |
| "language_info": { |
| "codemirror_mode": { |
| "name": "ipython", |
| "version": 3 |
| }, |
| "file_extension": ".py", |
| "mimetype": "text/x-python", |
| "name": "python", |
| "nbconvert_exporter": "python", |
| "pygments_lexer": "ipython3", |
| "version": "3.10.9" |
| } |
| }, |
| "nbformat": 4, |
| "nbformat_minor": 5 |
| } |