From 1d6ccef6238ca7ed3116c6ffe74d4473bef0ea64 Mon Sep 17 00:00:00 2001 From: srajan-kiyotaka Date: Wed, 19 Jun 2024 12:11:23 +0530 Subject: [PATCH 1/2] minor change in the methods of grid world. --- docs/gridWorld.md | 8 ++++---- setup.py | 9 +-------- src/traverseCraft/world.py | 4 ++-- tests/test_grid_agent.py | 4 ++-- tests/test_grid_world.py | 8 ++++---- 5 files changed, 13 insertions(+), 20 deletions(-) diff --git a/docs/gridWorld.md b/docs/gridWorld.md index 3298b51..a944fde 100644 --- a/docs/gridWorld.md +++ b/docs/gridWorld.md @@ -69,9 +69,9 @@ This method constructs the graphical user interface (GUI) representation of the - `None` -### `addBlockPath(self, blockCells:setOfCoordinates)` +### `setBlockPath(self, blockCells:setOfCoordinates)` -Adds block cells to the world grid, which are cells that cannot be traversed by an agent. It takes a set of coordinates representing the block cells and visually updates the grid to reflect these changes by coloring the corresponding cells in red. +sets block cells to the world grid, which are cells that cannot be traversed by an agent. It takes a set of coordinates representing the block cells and visually updates the grid to reflect these changes by coloring the corresponding cells in red. #### Parameters @@ -81,9 +81,9 @@ Adds block cells to the world grid, which are cells that cannot be traversed by - `None` -### `addGoalState(self, goalState:setOfCoordinates)` +### `setGoalState(self, goalState:setOfCoordinates)` -Adds goal cells to the world grid, which represents the target states an agent aims to reach. It takes a set of coordinates representing the goal cells and updates the grid by coloring these cells in green to visually differentiate them from other cells. +sets goal cells to the world grid, which represents the target states an agent aims to reach. It takes a set of coordinates representing the goal cells and updates the grid by coloring these cells in green to visually differentiate them from other cells. #### Parameters diff --git a/setup.py b/setup.py index 52ea6ef..a3bbfa1 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setup( name='TraverseCraft', - version='0.7.0', + version='0.7.5', author='Srajan Chourasia, Varun Patrikar', author_email='srajanstark.ash@gmail.com, patrikarvarun@gmail.com', maintainer='Srajan Chourasia, Varun Patrikar', @@ -34,13 +34,6 @@ 'License :: OSI Approved :: MIT License', 'Operating System :: OS Independent', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3.9', - 'Programming Language :: Python :: 3.10', - 'Programming Language :: Python :: 3.11', - 'Programming Language :: Python :: 3.12', 'Topic :: Education', 'Topic :: Software Development :: Libraries', 'Topic :: Software Development :: Libraries :: Python Modules', diff --git a/src/traverseCraft/world.py b/src/traverseCraft/world.py index 421f2c8..a2ec1df 100644 --- a/src/traverseCraft/world.py +++ b/src/traverseCraft/world.py @@ -279,7 +279,7 @@ def _startAgent(self): agentThread.start() - def addBlockPath(self, blockCells:setOfCoordinates): + def setBlockPath(self, blockCells:setOfCoordinates): """ Adds block cells to the world grid. @@ -299,7 +299,7 @@ def addBlockPath(self, blockCells:setOfCoordinates): self._world[i][j] = -1 - def addGoalState(self, goalState:setOfCoordinates): + def setGoalState(self, goalState:setOfCoordinates): """ Adds the goal state to the world grid. diff --git a/tests/test_grid_agent.py b/tests/test_grid_agent.py index 13d3d59..899b9b1 100644 --- a/tests/test_grid_agent.py +++ b/tests/test_grid_agent.py @@ -10,10 +10,10 @@ def setUp(self): self.grid_world = CreateGridWorld(worldName='Test Grid', rows=10, cols=10, cellSize=20, pathColor="black", blockColor="pink", goalColor="aqua", cellPadding=4, borderWidth=2, buttonBgColor="#7FC8D9", buttonFgColor="#332942", textFont="Helvetica", textSize=20, textWeight="bold", buttonText="Test Start Agent", logoPath=None) # Set goal state - self.grid_world.addGoalState([[5, 5], [6, 9], [8, 8]]) + self.grid_world.setGoalState([[5, 5], [6, 9], [8, 8]]) # Set block state - self.grid_world.addBlockPath([[1, 1], [2, 2], [3, 3], [2, 7], [8, 5], [6, 1]]) + self.grid_world.setBlockPath([[1, 1], [2, 2], [3, 3], [2, 7], [8, 5], [6, 1]]) # Construct the grid world self.grid_world.constructWorld() diff --git a/tests/test_grid_world.py b/tests/test_grid_world.py index ccf03de..20501a3 100644 --- a/tests/test_grid_world.py +++ b/tests/test_grid_world.py @@ -50,13 +50,13 @@ def test_cells_not_none_and_bound(self): block_path = [[1, 1], [2, 2], [3, 3], [2, 7], [8, 5], [6, 1]] # Add the block path to the grid world - self.grid_world.addBlockPath(block_path) + self.grid_world.setBlockPath(block_path) # Define the goal state to be added goal_state = [[5, 5], [6, 9], [8, 8]] # Add the goal state to the grid world - self.grid_world.addGoalState(goal_state) + self.grid_world.setGoalState(goal_state) # Construct the grid world self.grid_world.constructWorld() @@ -80,7 +80,7 @@ def test_add_block_path(self): block_path = [[1, 1], [2, 2], [3, 3], [2, 7], [8, 5], [6, 1]] # Add the block path to the grid world - self.grid_world.addBlockPath(block_path) + self.grid_world.setBlockPath(block_path) # Verify that the cells corresponding to the block path are set correctly for coordinate in block_path: @@ -98,7 +98,7 @@ def test_add_goal_state(self): goal_state = [[5, 5], [6, 9], [8, 8]] # Add the goal state to the grid world - self.grid_world.addGoalState(goal_state) + self.grid_world.setGoalState(goal_state) # Verify that the cells corresponding to the goal state are set correctly for coordinate in goal_state: From 77d8c54229a169bac83c53d057d72ec3f3d28013 Mon Sep 17 00:00:00 2001 From: srajan-kiyotaka Date: Wed, 19 Jun 2024 13:20:45 +0530 Subject: [PATCH 2/2] completed the tutorial for grid world simulation. --- tutorials/Grid World/advance.ipynb | 888 ++++++++++++++++++++++++++++ tutorials/Grid World/beginner.ipynb | 71 ++- 2 files changed, 923 insertions(+), 36 deletions(-) create mode 100644 tutorials/Grid World/advance.ipynb diff --git a/tutorials/Grid World/advance.ipynb b/tutorials/Grid World/advance.ipynb new file mode 100644 index 0000000..e68b217 --- /dev/null +++ b/tutorials/Grid World/advance.ipynb @@ -0,0 +1,888 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Import required modules\n", + "\n", + "Let's start by importing the required module form the main library.\n", + "\n", + "It's always a good idea to check whether the library is installed or not. The below command will install the library if the library is not already installed." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Looking in indexes: https://test.pypi.org/simple/\n", + "Requirement already satisfied: TraverseCraft in /media/srajan/Data/Project/LibraryTests/envs/lib/python3.8/site-packages (0.7.5)\n", + "Requirement already satisfied: prettytable in /media/srajan/Data/Project/LibraryTests/envs/lib/python3.8/site-packages (from TraverseCraft) (0.7.3.dev122)\n" + ] + } + ], + "source": [ + "!pip install -i https://test.pypi.org/simple/ TraverseCraft" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Let's import Grid World and Grid Agent\n", + "we will import the `CreateGridWorld` class from the `world` module and `GridAgent` class from the `agent` module.\n", + "\n", + "> **Note:** *It is very important to call the right agent for the given world, otherwise the module will through an error. Each world behave differently and each agent is tailored for that world only.*\n", + "\n", + "> **Remark:** *Don't worry if during the importing the library prints the OS Type. Actually the library uses some internal variables which are OS depended. It is necessary that the os type printed and your OS type matches. If it does't match please [report this]().*" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "OS Type: Linux\n" + ] + } + ], + "source": [ + "from traverseCraft.world import CreateGridWorld\n", + "from traverseCraft.agent import GridAgent" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Create a Grid World\n", + "Let's start with creating a 10 x 10 Grid world. But this time we will not use the default settings and will customize our world.\n", + "We will make the following changes:\n", + "- `cellSize`: Controls the size of each cell in the grid.\n", + "- `pathColor`: Set's the color of all the cells where the agent can move.\n", + "- `blockColor`: Set's the color of all the cells where the agent can not move.\n", + "- `goalColor`: Set the color of all the goal states. \n", + "we will set the following color for each type of cell:\n", + "- **Path:** green color\n", + "- **Block:** ref color\n", + "- **Goal:** gray color" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "# First let's Create a grid world object!\n", + "gridWorld = CreateGridWorld(worldName=\"Custom Grid World\", rows=10, cols=10, cellSize=30, pathColor=\"green\", blockColor=\"red\", goalColor=\"gray\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Compile our Grid World\n", + "It is always a good idea to compile the world before doing any changes or modifications into the world.\n", + "\n", + "> **Note:** *It is recommended to do all the changes in the world after compiling the world. Although you can change the world even before the compilation but then the world will show some partial information before compiling the world takes place.*\n", + "\n", + "> **Warning:** *Don't worry if the window showed up. Please don't destroy the window. This is due to the fact that the cell in jupyter notebook is running the process and the frame generated will reflect all the changes done after this point. If you destroy the window then it will show error.*" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "gridWorld.constructWorld()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Add Block and Goal States\n", + "You may be wondering what the goal and block states were in the previous section. So the main goal of this library is to run simulations right!. Thus it make sense that the simulated world should have some cells which are walls or block or restricted areas which are the block cells and there should also some goal states which are the goal cells.\n", + "\n", + "> **Note:** a world can have none block states but it must have at least 1 goal state. Also a world can have more than 1 goal state and can also have more than 1 block states. But make the goal state can't be a block state.\n", + "\n", + "By default the goal state will be the bottom right corner cell.\n", + "\n", + "We will change the goal state and set some cells to be the block states.\n", + "- The block state cells are [[2,2], [3,6], [1,1], [7,8], [9,1], [0,5]]\n", + "- The goal state cells are [[5,6], [9,1]] \n", + "\n", + "To achieve this we will use the `setBlockPath()` and `setGoalState()` methods.\n", + "\n", + "> **Note:** onces you execute the below command you will see the window opened after the world compilation will reflect all the changes. This way you can verify the changes in your world. " + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "# Block cells\n", + "blockCells = [[2,2], [3,6], [1,1], [7,8], [9,1], [0,5]]\n", + "gridWorld.setBlockPath(blockCells)\n", + "\n", + "# Goal cells\n", + "goalCells = [[5,6], [9,1]]\n", + "gridWorld.setGoalState(goalCells)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Undo a Change\n", + "Assume you want to set another set of cells as block or goal states, then one way is to simple run the `setBlockPath()` or `setGoalState()` method again with the new set of cells coordinates to refresh the block or goal state cells.\n", + "\n", + "> **Note:** when you rerun the method, it will reset the state to the new set of cells, it will not extend or add the cells to the previously existing cells.\n", + "\n", + "### let's refresh the block and goal state\n", + "- add [[0,3], [7,0]] to our existing block state.\n", + "- add [[0, 9], [7, 6]] to our existing goal state.\n", + "\n", + "The changes will be reflected in the window." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "# extend the block cells\n", + "blockCells.extend([[0,3], [7, 0]])\n", + "gridWorld.setBlockPath(blockCells)\n", + "\n", + "# extend the goal cells\n", + "goalCells.extend([[0,9], [7,6]])\n", + "gridWorld.setGoalState(goalCells)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "> **Warning:** *You can toggle between the block state and path state, But once a cell is set to goal state you can not change the state of the cell.*\n", + "\n", + "### Let's see some basic information about our *Grid World*!\n", + "you can use a simple `print()` statement or you can use the builtin function `aboutWorld()` to get the world information as a string." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "+-------------------------+-------------------+\n", + "| Attribute | Value |\n", + "+-------------------------+-------------------+\n", + "| World Name | Custom Grid World |\n", + "| Rows | 10 |\n", + "| Columns | 10 |\n", + "| Cell Size | 30 |\n", + "| Cell Padding | 2 |\n", + "| Window Size | 402x357 |\n", + "| Path Color | green |\n", + "| Block Color | red |\n", + "| Goal Color | gray |\n", + "| Border Width | 1 |\n", + "| Button Background Color | #7FC7D9 |\n", + "| Button Foreground Color | #332941 |\n", + "| Button Text | Start Agent |\n", + "| Text Font | Helvetica |\n", + "| Text Size | 24 |\n", + "| Text Weight | bold |\n", + "+-------------------------+-------------------+\n" + ] + } + ], + "source": [ + "print(gridWorld)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Help\n", + "If you want to know more information about any method, or variable, you can simple use the `help()` function to get more information. Or you can visit our official [website]() to get more information." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Help on CreateGridWorld in module traverseCraft.world object:\n", + "\n", + "class CreateGridWorld(builtins.object)\n", + " | CreateGridWorld(worldName: str, rows: int, cols: int, cellSize: int = 20, pathColor: str = 'gray', blockColor: str = 'red', goalColor: str = 'green', cellPadding: int = 2, borderWidth: int = 1, buttonBgColor: str = '#7FC7D9', buttonFgColor: str = '#332941', textFont: str = 'Helvetica', textSize: int = 24, textWeight: str = 'bold', buttonText: str = 'Start Agent', logoPath: str = None)\n", + " | \n", + " | Class representing the world created using Grids.\n", + " | \n", + " | Attributes:\n", + " | setOfCoordinates (List[List[int]]): A list of coordinates.\n", + " | coordinate (List[int]): A list representing a coordinate.\n", + " | worldID (str): The ID of the world.\n", + " | \n", + " | Args:\n", + " | _worldName (str): The name of the world.\n", + " | _rows (int): The number of rows in the world. (Between 0 and 50)\n", + " | _cols (int): The number of columns in the world. (Between 0 and 50)\n", + " | _logoPath (str): The path to the logo image.\n", + " | _world (List[List[int]]): A 2D list representing the world.\n", + " | _blockCells (setOfCoordinates): A set of coordinates representing the block cells.\n", + " | _cellSize (int): The size of each cell in pixels.Defaults to 10. (Between 10 and 60)\n", + " | _pathColor (str): The color of the path cells. Defaults to \"gray\".\n", + " | _cellPadding (int): The padding around each cell in pixels. Defaults to 2.\n", + " | _blockColor (str): The color of the block cells. Defaults to \"red\".\n", + " | _borderWidth (int): The width of the cell borders in pixels. Defaults to 1.\n", + " | _goalColor (str): The color of the goal cells. Defaults to \"green\".\n", + " | _goalCells (setOfCoordinates): A set of coordinates representing the goal cells.\n", + " | _buttonBgColor (str): The background color of the button. Defaults to \"#7FC7D9\".\n", + " | _buttonFgColor (str): The foreground color of the button. Defaults to \"#332941\".\n", + " | _textFont (str): The font of the button text. Defaults to \"Helvetica\".\n", + " | _textSize (int): The size of the button text. Defaults to 24.\n", + " | _textWeight (str): The weight of the button text. Defaults to \"bold\".\n", + " | _buttonText (str): The text displayed on the button. Defaults to \"Start Agent\".\n", + " | _root (Tk): The root window of the world.\n", + " | _agent (Agent): The agent object.\n", + " | _logoPath (str): The path to the logo image.\n", + " | \n", + " | Methods defined here:\n", + " | \n", + " | __init__(self, worldName: str, rows: int, cols: int, cellSize: int = 20, pathColor: str = 'gray', blockColor: str = 'red', goalColor: str = 'green', cellPadding: int = 2, borderWidth: int = 1, buttonBgColor: str = '#7FC7D9', buttonFgColor: str = '#332941', textFont: str = 'Helvetica', textSize: int = 24, textWeight: str = 'bold', buttonText: str = 'Start Agent', logoPath: str = None)\n", + " | Initializes the Grid World.\n", + " | \n", + " | __str__(self)\n", + " | Describes the attributes of the world.\n", + " | \n", + " | Parameters:\n", + " | None\n", + " | \n", + " | Returns:\n", + " | function(): The attributes of the world.\n", + " | \n", + " | aboutWorld(self)\n", + " | Describes the attributes of the world.\n", + " | \n", + " | Parameters:\n", + " | None\n", + " | \n", + " | Returns:\n", + " | str: The attributes of the world.\n", + " | \n", + " | constructWorld(self)\n", + " | Constructs the world by creating and arranging cells in the GUI.\n", + " | If the goal cells are not set, it creates a goal cell at the bottom-right corner of the grid.\n", + " | It also creates cells for each row and column in the grid, and binds a left-click event to toggle the cells.\n", + " | Finally, it creates a \"Start Agent\" button at the bottom of the grid.\n", + " | \n", + " | Parameters:\n", + " | None\n", + " | \n", + " | Returns:\n", + " | None\n", + " | \n", + " | setAgent(self, agent)\n", + " | Set the agent for the world.\n", + " | \n", + " | Parameters:\n", + " | agent (Agent): The agent object to set.\n", + " | \n", + " | Returns:\n", + " | None\n", + " | \n", + " | setBlockPath(self, blockCells: List[List[int]])\n", + " | Adds block cells to the world grid.\n", + " | \n", + " | Parameters:\n", + " | blockCells (setOfCoordinates): A set of coordinates representing the block cells.\n", + " | \n", + " | Returns:\n", + " | None\n", + " | \n", + " | setGoalState(self, goalState: List[List[int]])\n", + " | Adds the goal state to the world grid.\n", + " | \n", + " | Parameters:\n", + " | goalState (setOfCoordinates): A set of coordinates representing the goal state.\n", + " | \n", + " | Returns:\n", + " | None\n", + " | \n", + " | showWorld(self)\n", + " | Displays the world.\n", + " | \n", + " | Parameters:\n", + " | None\n", + " | \n", + " | Returns:\n", + " | None\n", + " | \n", + " | summary(self)\n", + " | Generates a summary of the world.\n", + " | \n", + " | Parameters:\n", + " | None\n", + " | \n", + " | Returns:\n", + " | str: The summary of the world.\n", + " | \n", + " | updateWorld(self)\n", + " | Updates the world by positioning the cells in a grid layout and updating the root window.\n", + " | \n", + " | This method iterates over each cell in the world and positions it in a grid layout using the row and column indices.\n", + " | It also updates the root window to reflect any changes made to the world.\n", + " | \n", + " | Note:\n", + " | - The cells are positioned using the `grid` method with the specified row and column indices.\n", + " | - The `sticky` parameter is set to \"nsew\" to make the cells stick to all sides of their respective grid cells.\n", + " | - The `padx` and `pady` parameters specify the padding around each cell.\n", + " | \n", + " | Parameters:\n", + " | None\n", + " | Returns:\n", + " | None\n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Data descriptors defined here:\n", + " | \n", + " | __dict__\n", + " | dictionary for instance variables (if defined)\n", + " | \n", + " | __weakref__\n", + " | list of weak references to the object (if defined)\n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Data and other attributes defined here:\n", + " | \n", + " | coordinate = typing.List[int]\n", + " | The central part of internal API.\n", + " | \n", + " | This represents a generic version of type 'origin' with type arguments 'params'.\n", + " | There are two kind of these aliases: user defined and special. The special ones\n", + " | are wrappers around builtin collections and ABCs in collections.abc. These must\n", + " | have 'name' always set. If 'inst' is False, then the alias can't be instantiated,\n", + " | this is used by e.g. typing.List and typing.Dict.\n", + " | \n", + " | setOfCoordinates = typing.List[typing.List[int]]\n", + " | The central part of internal API.\n", + " | \n", + " | This represents a generic version of type 'origin' with type arguments 'params'.\n", + " | There are two kind of these aliases: user defined and special. The special ones\n", + " | are wrappers around builtin collections and ABCs in collections.abc. These must\n", + " | have 'name' always set. If 'inst' is False, then the alias can't be instantiated,\n", + " | this is used by e.g. typing.List and typing.Dict.\n", + " | \n", + " | worldID = 'GRIDWORLD'\n", + "\n" + ] + } + ], + "source": [ + "help(gridWorld)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Let's create our agent which will interact with the world.\n", + "We will create a grid agent with the following custom settings.\n", + "- `agentColor`: set the color of the cell where is the agent.\n", + "- `heatMapView`: set True or False to decide whether to see the heatmap in realtime in simulation or not.\n", + "- `agentPos`: set the beginning cell coordinates of the agent.\n", + "\n", + "we will set the values to the following:\n", + "- **agentColor:** aqua\n", + "- **heatMapView:** False(to only see the simulation)\n", + "- **agentPos:** (4,4)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "startState = (4,4)\n", + "\n", + "gridAgent = GridAgent(agentName=\"Grid Agent\", world=gridWorld, agentColor=\"aqua\", heatMapView=False, agentPos=startState)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can see the agent position get reflected in the window.\n", + "\n", + "## Let's see some basic information about our `grid Agent`.\n", + "you can use a simple `print()` statement or you can use the builtin function `aboutAgent()` to get the agent information as a string." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "+----------------+-------------------+\n", + "| Attribute | Value |\n", + "+----------------+-------------------+\n", + "| Agent Name | Grid Agent |\n", + "| Agent Color | aqua |\n", + "| World Name | Custom Grid World |\n", + "| World ID | GRIDWORLD |\n", + "| Start Position | (4, 4) |\n", + "+----------------+-------------------+\n" + ] + } + ], + "source": [ + "print(gridAgent)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Connect Our Agent with the World\n", + "Now, we have our world ready and constructed and we also have our agent ready, but the world doesn't know the agent and the agent does't know the world. We have to connect the agent with the world. We will use the `.setAgent()` method of the world to connect the agent with the world. " + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "gridWorld.setAgent(gridAgent)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Algorithm\n", + "Now, we have connected the agent with the world, but we did not told the agent what to do in the world.\n", + "\n", + "The agent have a method `setAlgorithmCallBack()` which takes a function as a argument.\n", + "This function will be run during the simulation.\n", + "> **Note:** *Make sure that the function you are passing in the `setAlgorithmCallBack()` method does not take any argument.*\n", + "\n", + "## Let's first create our Algorithm that will move the agent.\n", + "We will write a simple DFS algorithm to move our agent, and our main goal will be to get to any goal state.\n", + "\n", + "### Some Useful methods\n", + "- `checkGoalState()` method is use to check whether the given coordinate is a goal state or not.\n", + "- `checkBlockState()` method is use to check whether the given coordinate is a block state or not.\n", + "- `moveAgent()` this method will return False if it is not possible to move the agent to the given cell coordinates or will move the agent and return True if it is possible. We can also control the delay in the movement.\n", + "\n", + "#### DFS Algorithm" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "def dfs(agent, i, j, visited):\n", + " if(agent.checkGoalState(i, j)):\n", + " return True\n", + " if(visited[i][j]):\n", + " return False\n", + " visited[i][j] = True\n", + " # move up\n", + " if(i > 0 and not visited[i-1][j] and agent.moveAgent(i-1, j)):\n", + " if(dfs(agent, i-1, j, visited)):\n", + " return True\n", + " agent.moveAgent(i, j)\n", + " # move down\n", + " if(i < 9 and not visited[i+1][j] and agent.moveAgent(i+1, j)):\n", + " if(dfs(agent, i+1, j, visited)):\n", + " return True\n", + " agent.moveAgent(i, j)\n", + " # move left\n", + " if(j > 0 and not visited[i][j-1] and agent.moveAgent(i, j-1)):\n", + " if(dfs(agent, i, j-1, visited)):\n", + " return True\n", + " agent.moveAgent(i, j)\n", + " # move right\n", + " if(j < 9 and not visited[i][j+1] and agent.moveAgent(i, j+1)):\n", + " if(dfs(agent, i, j+1, visited)):\n", + " return True\n", + " agent.moveAgent(i, j)\n", + " return False" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### We will use the dfs Algorithm in the main callback function\n", + "> **Remember:** *Since the call back function will only accept a function with no arguments, thus it is always a good idea to create another function which takes the arguments and use that function in the call back function.*" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "def toDo():\n", + " visited = [[False for _ in range(10)] for _ in range(10)]\n", + " print(\"Agent Started moving around the world!\")\n", + " if(dfs(gridAgent, startState[0], startState[1], visited))\n", + " print(\"Agent reached the goal state!\")\n", + " else:\n", + " print(\"Agent could not reach the goal state!\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### We are ready with our algorithm\n", + "Lets set the algorithm to tell the agent what to do. " + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "gridAgent.setAlgorithmCallBack(toDo)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Display the world and Start the Simulation!\n", + "Now, we are all set. We will first show the world using the `showWorld()` method and then on the world there is a button at the bottom to start the simulation.\n", + "\n", + "> **Fun Fact:** *You can click on any non goal cell to toggle between block and path state.*\n", + "\n", + "> **Warning:** *Always make sure that the method `showWorld()` is called when you are ready to simulate, because after this no change can be made on the world or the agent.*" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Agent Started moving around the world!\n", + "I am done moving around the world!\n" + ] + } + ], + "source": [ + "gridWorld.showWorld()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the window You can see the heatmap forming where the agent is going. This is the default function of the agent, but you can switch off this feature also by simple changing the value of `heatMapView` to `False` during the grid agent object creation.\n", + "\n", + "You can also see there is a slight delay in the movement of the agent, this is also a feature of agent, you can control the delay while calling the `moveAgent` method by the parameter `delay`.\n", + "\n", + "## Let's see the summary\n", + "\n", + "The agent and the world keep some records, that we can generate and see.\n", + "\n", + "### The Agent have information about the time taken to run the whole simulation.\n", + "We can see this information using the `summary` method." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "+--------------+---------------------------+\n", + "| Attribute | Value |\n", + "+--------------+---------------------------+\n", + "| Start Time | Wed, 19 Jun 2024 07:37:08 |\n", + "| End Time | Wed, 19 Jun 2024 07:37:31 |\n", + "| Elapsed Time | 23.098 sec |\n", + "+--------------+---------------------------+\n" + ] + } + ], + "source": [ + "print(gridAgent.summary())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### The World have information about the visited count after the whole simulation.\n", + "We can see this information using the `summary` method." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "+------+---+---+---+---+---+---+---+---+---+---+\n", + "| Cell | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |\n", + "+------+---+---+---+---+---+---+---+---+---+---+\n", + "| 0 | 2 | 2 | 2 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |\n", + "| 1 | 2 | 0 | 1 | 1 | 2 | 0 | 0 | 0 | 0 | 0 |\n", + "| 2 | 2 | 1 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 |\n", + "| 3 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 |\n", + "| 4 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 |\n", + "| 5 | 1 | 2 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |\n", + "| 6 | 1 | 2 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |\n", + "| 7 | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |\n", + "| 8 | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |\n", + "| 9 | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |\n", + "+------+---+---+---+---+---+---+---+---+---+---+\n" + ] + } + ], + "source": [ + "print(gridWorld.summary())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Help\n", + "If you want to know more information about any method, or variable, you can simple use the `help()` function to get more information. Or you can visit our official [website]() to get more information." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Help on GridAgent in module traverseCraft.agent object:\n", + "\n", + "class GridAgent(builtins.object)\n", + " | GridAgent(world, agentName: str, agentColor: str = 'blue', heatMapView: bool = True, heatMapColor: str = '#FFA732', agentPos: tuple = (0, 0), heatGradient: float = 0.05)\n", + " | \n", + " | The Grid Agent class.\n", + " | \n", + " | Parameters:\n", + " | - world (CreateGridWorld): The grid world object in which the agent operates.\n", + " | - agentName (str): The name of the agent.\n", + " | - agentColor (str, optional): The color of the agent. Defaults to \"blue\".\n", + " | - heatMapView (bool, optional): Whether to enable the heat map view. Defaults to True.\n", + " | - heatMapColor (str, optional): The color of the heat map. Defaults to \"#FFA732\".\n", + " | - agentPos (tuple, optional): The initial position of the agent. Defaults to (0, 0).\n", + " | - heatGradient (float, optional): The gradient value for the heat map. Defaults to 0.05.\n", + " | \n", + " | Attributes:\n", + " | _worldObj (CreateGridWorld): The grid world object.\n", + " | _worldID (str): The ID of the world.\n", + " | _root (Tk): The root Tkinter object from the grid world.\n", + " | _agentName (str): The name of the agent.\n", + " | _agentColor (str): The color of the agent.\n", + " | _heatMapView (bool): Indicates if the heat map view is enabled.\n", + " | _heatMapColor (str): The color of the heat map.\n", + " | _heatMapBaseColor (str): The base color of the heat map.\n", + " | _heatGradient (float): The gradient value for the heat map.\n", + " | _startState (tuple): The initial position of the agent.\n", + " | _currentPosition (tuple): The current position of the agent.\n", + " | _startTime (float): The start time of the agent.\n", + " | _endTime (float): The end time of the agent.\n", + " | algorithmCallBack (function): Callback function for the agent's algorithm.\n", + " | \n", + " | Methods defined here:\n", + " | \n", + " | __init__(self, world, agentName: str, agentColor: str = 'blue', heatMapView: bool = True, heatMapColor: str = '#FFA732', agentPos: tuple = (0, 0), heatGradient: float = 0.05)\n", + " | Initialize self. See help(type(self)) for accurate signature.\n", + " | \n", + " | __str__(self)\n", + " | Describes the attributes of the world.\n", + " | \n", + " | Parameters:\n", + " | None\n", + " | \n", + " | Returns:\n", + " | function(): The attributes of the world.\n", + " | \n", + " | aboutAgent(self)\n", + " | Prints information about the agent.\n", + " | \n", + " | Parameters:\n", + " | None\n", + " | \n", + " | Returns:\n", + " | str: A string containing information about the agent.\n", + " | \n", + " | checkBlockState(self, i, j)\n", + " | Check the state of a block in the world.\n", + " | \n", + " | Parameters:\n", + " | i (int): The row index of the block.\n", + " | j (int): The column index of the block.\n", + " | \n", + " | Returns:\n", + " | bool: True if the block is empty (-1), False otherwise.\n", + " | \n", + " | checkGoalState(self, i, j)\n", + " | Check if the given position (i, j) is a goal state.\n", + " | \n", + " | Parameters:\n", + " | i (int): The row index of the position.\n", + " | j (int): The column index of the position.\n", + " | \n", + " | Returns:\n", + " | bool: True if the position is a goal state, False otherwise.\n", + " | \n", + " | getHeatMapColor(self, value: float)\n", + " | Maps a value to a color on a heat map.\n", + " | \n", + " | Args:\n", + " | value (float): The value to be mapped.\n", + " | \n", + " | Returns:\n", + " | tuple: The RGB color tuple representing the mapped value on the heat map.\n", + " | \n", + " | moveAgent(self, i, j, delay: float = 0.5)\n", + " | Moves the agent to the specified position (i, j) on the grid.\n", + " | \n", + " | Args:\n", + " | i (int): The row index of the target position.\n", + " | j (int): The column index of the target position.\n", + " | delay (int, optional): The delay in seconds before moving the agent. Defaults to 1.\n", + " | \n", + " | Returns:\n", + " | bool: True if the agent successfully moves to the target position, False otherwise.\n", + " | \n", + " | runAlgorithm(self)\n", + " | Executes the algorithm callback function.\n", + " | \n", + " | Raises:\n", + " | ValueError: If the algorithm callback function is not set.\n", + " | \n", + " | setAlgorithmCallBack(self, algorithmCallBack)\n", + " | Set the callback function for the algorithm.\n", + " | \n", + " | Parameters:\n", + " | algorithmCallBack (function): The callback function to be set.\n", + " | \n", + " | Returns:\n", + " | None\n", + " | \n", + " | setStartState(self, i: int, j: int)\n", + " | Sets the start state of the agent to the specified position (i, j).\n", + " | \n", + " | Args:\n", + " | i (int): The row index of the start position.\n", + " | j (int): The column index of the start position.\n", + " | \n", + " | Raises:\n", + " | ValueError: If the specified start position is invalid.\n", + " | \n", + " | summary(self)\n", + " | Returns a summary of the agent run.\n", + " | \n", + " | Parameters: \n", + " | None\n", + " | Returns:\n", + " | str: A summary of the agent run.\n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Data descriptors defined here:\n", + " | \n", + " | __dict__\n", + " | dictionary for instance variables (if defined)\n", + " | \n", + " | __weakref__\n", + " | list of weak references to the object (if defined)\n", + "\n" + ] + } + ], + "source": [ + "help(gridAgent)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This covers all the required features and knowledge required to create simulations for Grid World.\n", + "\n", + "Next, please refer the [API Reference]() section for more details regarding each class and methods.\n", + "\n", + "Thanks!" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.8.19" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/tutorials/Grid World/beginner.ipynb b/tutorials/Grid World/beginner.ipynb index a038f63..e6b70f0 100644 --- a/tutorials/Grid World/beginner.ipynb +++ b/tutorials/Grid World/beginner.ipynb @@ -8,14 +8,12 @@ "\n", "Let's start by importing the required module form the main library.\n", "\n", - "It's always a good idea to check whether the library is installed or not.\n", - "\n", - "This command will install if the library is not already installed." + "It's always a good idea to check whether the library is installed or not. The below command will install the library if the library is not already installed." ] }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 1, "metadata": {}, "outputs": [ { @@ -23,7 +21,7 @@ "output_type": "stream", "text": [ "Looking in indexes: https://test.pypi.org/simple/\n", - "Requirement already satisfied: TraverseCraft in /media/srajan/Data/Project/LibraryTests/envs/lib/python3.8/site-packages (0.6.5)\n", + "Requirement already satisfied: TraverseCraft in /media/srajan/Data/Project/LibraryTests/envs/lib/python3.8/site-packages (0.7.5)\n", "Requirement already satisfied: prettytable in /media/srajan/Data/Project/LibraryTests/envs/lib/python3.8/site-packages (from TraverseCraft) (0.7.3.dev122)\n" ] } @@ -39,13 +37,14 @@ "## Let's import Grid World and Grid Agent\n", "we will import the `CreateGridWorld` class from the `world` module and `GridAgent` class from the `agent` module.\n", "\n", - "It is very important to call the right agent for the given world, otherwise the module will through an error. \n", - "Each world behave differently and each agent is tailored for that world only." + "> **Note:** *It is very important to call the right agent for the given world, otherwise the module will through an error. Each world behave differently and each agent is tailored for that world only.*\n", + "\n", + "> **Remark:** *Don't worry if during the importing the library prints the OS Type. Actually the library uses some internal variables which are OS depended. It is necessary that the os type printed and your OS type matches. If it does't match please [report this]().*" ] }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 2, "metadata": {}, "outputs": [ { @@ -73,7 +72,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -88,7 +87,7 @@ "## Compile our Hello Grid World\n", "since, we are just creating a simple grid world with all the default settings, we are ready to compile our world.\n", "\n", - "> **Note:** *It is recommended to do all the changes in the world before compiling the world. Although you can change the world even after the compilation but then the world will take time to update the changes as it will have more process to run now.*" + "> **Note:** *It is recommended to do all the changes in the world after compiling the world. Although you can change the world even before the compilation but then the world will show some partial information before compiling the world takes place.*" ] }, { @@ -104,7 +103,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "> *Don't worry if the window showed up or if you are unable to cut the window. This is due to the fact that the cell in jupyter notebook is running the process.*\n", + "> **Warning:** *Don't worry if the window showed up. Please don't destroy the window. This is due to the fact that the cell in jupyter notebook is running the process and the frame generated will reflect all the changes done after this point. If you destroy the window then it will show error.*\n", "\n", "### Let's see some basic information about our *Hello World*!\n", "you can use a simple `print()` statement or you can use the builtin function `aboutWorld()` to get the world information as a string." @@ -125,9 +124,9 @@ "| World Name | Hello World |\n", "| Rows | 8 |\n", "| Columns | 8 |\n", - "| Cell Size | 10 |\n", + "| Cell Size | 20 |\n", "| Cell Padding | 2 |\n", - "| Window Size | 164x200 |\n", + "| Window Size | 249x204 |\n", "| Path Color | gray |\n", "| Block Color | red |\n", "| Goal Color | green |\n", @@ -161,9 +160,9 @@ "| World Name | Hello World |\n", "| Rows | 8 |\n", "| Columns | 8 |\n", - "| Cell Size | 10 |\n", + "| Cell Size | 20 |\n", "| Cell Padding | 2 |\n", - "| Window Size | 164x200 |\n", + "| Window Size | 249x204 |\n", "| Path Color | gray |\n", "| Block Color | red |\n", "| Goal Color | green |\n", @@ -202,7 +201,7 @@ "Help on CreateGridWorld in module traverseCraft.world object:\n", "\n", "class CreateGridWorld(builtins.object)\n", - " | CreateGridWorld(worldName: str, rows: int, cols: int, cellSize: int = 10, pathColor: str = 'gray', blockColor: str = 'red', goalColor: str = 'green', cellPadding: int = 2, borderWidth: int = 1, buttonBgColor: str = '#7FC7D9', buttonFgColor: str = '#332941', textFont: str = 'Helvetica', textSize: int = 24, textWeight: str = 'bold', buttonText: str = 'Start Agent', logoPath: str = None)\n", + " | CreateGridWorld(worldName: str, rows: int, cols: int, cellSize: int = 20, pathColor: str = 'gray', blockColor: str = 'red', goalColor: str = 'green', cellPadding: int = 2, borderWidth: int = 1, buttonBgColor: str = '#7FC7D9', buttonFgColor: str = '#332941', textFont: str = 'Helvetica', textSize: int = 24, textWeight: str = 'bold', buttonText: str = 'Start Agent', logoPath: str = None)\n", " | \n", " | Class representing the world created using Grids.\n", " | \n", @@ -237,7 +236,7 @@ " | \n", " | Methods defined here:\n", " | \n", - " | __init__(self, worldName: str, rows: int, cols: int, cellSize: int = 10, pathColor: str = 'gray', blockColor: str = 'red', goalColor: str = 'green', cellPadding: int = 2, borderWidth: int = 1, buttonBgColor: str = '#7FC7D9', buttonFgColor: str = '#332941', textFont: str = 'Helvetica', textSize: int = 24, textWeight: str = 'bold', buttonText: str = 'Start Agent', logoPath: str = None)\n", + " | __init__(self, worldName: str, rows: int, cols: int, cellSize: int = 20, pathColor: str = 'gray', blockColor: str = 'red', goalColor: str = 'green', cellPadding: int = 2, borderWidth: int = 1, buttonBgColor: str = '#7FC7D9', buttonFgColor: str = '#332941', textFont: str = 'Helvetica', textSize: int = 24, textWeight: str = 'bold', buttonText: str = 'Start Agent', logoPath: str = None)\n", " | Initializes the Grid World.\n", " | \n", " | __str__(self)\n", @@ -258,41 +257,41 @@ " | Returns:\n", " | str: The attributes of the world.\n", " | \n", - " | addBlockPath(self, blockCells: List[List[int]])\n", - " | Adds block cells to the world grid.\n", + " | constructWorld(self)\n", + " | Constructs the world by creating and arranging cells in the GUI.\n", + " | If the goal cells are not set, it creates a goal cell at the bottom-right corner of the grid.\n", + " | It also creates cells for each row and column in the grid, and binds a left-click event to toggle the cells.\n", + " | Finally, it creates a \"Start Agent\" button at the bottom of the grid.\n", " | \n", " | Parameters:\n", - " | blockCells (setOfCoordinates): A set of coordinates representing the block cells.\n", + " | None\n", " | \n", " | Returns:\n", " | None\n", " | \n", - " | addGoalState(self, goalState: List[List[int]])\n", - " | Adds the goal state to the world grid.\n", + " | setAgent(self, agent)\n", + " | Set the agent for the world.\n", " | \n", " | Parameters:\n", - " | goalState (setOfCoordinates): A set of coordinates representing the goal state.\n", + " | agent (Agent): The agent object to set.\n", " | \n", " | Returns:\n", " | None\n", " | \n", - " | constructWorld(self)\n", - " | Constructs the world by creating and arranging cells in the GUI.\n", - " | If the goal cells are not set, it creates a goal cell at the bottom-right corner of the grid.\n", - " | It also creates cells for each row and column in the grid, and binds a left-click event to toggle the cells.\n", - " | Finally, it creates a \"Start Agent\" button at the bottom of the grid.\n", + " | setBlockPath(self, blockCells: List[List[int]])\n", + " | Adds block cells to the world grid.\n", " | \n", " | Parameters:\n", - " | None\n", + " | blockCells (setOfCoordinates): A set of coordinates representing the block cells.\n", " | \n", " | Returns:\n", " | None\n", " | \n", - " | setAgent(self, agent)\n", - " | Set the agent for the world.\n", + " | setGoalState(self, goalState: List[List[int]])\n", + " | Adds the goal state to the world grid.\n", " | \n", " | Parameters:\n", - " | agent (Agent): The agent object to set.\n", + " | goalState (setOfCoordinates): A set of coordinates representing the goal state.\n", " | \n", " | Returns:\n", " | None\n", @@ -579,9 +578,9 @@ "+--------------+---------------------------+\n", "| Attribute | Value |\n", "+--------------+---------------------------+\n", - "| Start Time | Mon, 17 Jun 2024 17:25:04 |\n", - "| End Time | Mon, 17 Jun 2024 17:25:13 |\n", - "| Elapsed Time | 8.539 sec |\n", + "| Start Time | Wed, 19 Jun 2024 06:44:52 |\n", + "| End Time | Wed, 19 Jun 2024 06:45:01 |\n", + "| Elapsed Time | 8.533 sec |\n", "+--------------+---------------------------+\n" ] } @@ -793,7 +792,7 @@ "source": [ "This covers the basic of how to create a simple Grid World and Grid Agent. How to connect the created agent with the world and how to run a simple algorithm to simulate the agent on the world.\n", "\n", - "Next, in the `Intermediate Section` we will learn about how to use advance features and settings to customize the world according to your need.\n", + "Next, in the `Advance Section` we will learn about how to use some advance features and settings to customize the world according to your need.\n", "\n", "Thanks!" ]