Quick Links
Beginner Section
Learn how to take your first steps using Traversecraft with this tutorial.
Import required modules¶
Let's start by importing the required module form the main library.
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.
!pip install -i https://test.pypi.org/simple/ TraverseCraft
Looking in indexes: https://test.pypi.org/simple/ Requirement already satisfied: TraverseCraft in /media/srajan/Data/Project/LibraryTests/envs/lib/python3.8/site-packages (0.8.5) Requirement already satisfied: prettytable in /media/srajan/Data/Project/LibraryTests/envs/lib/python3.8/site-packages (from TraverseCraft) (0.7.3.dev122)
Let's import Tree World and Tree Agent¶
we will import the CreateTreeWorld
class from the world
module and TreeAgent
class from the agent
module.
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.
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.
from traverseCraft.world import CreateTreeWorld
from traverseCraft.agent import TreeAgent
OS Type: Linux
Hello Tree World¶
Let's start with a simple Hello Tree World program to get familiarize with the library.
We will create a simple complete binary tree of height 3 with the default settings on.
World Information¶
Before creating the Tree World we have to first create the world blueprint/template. We call this blueprint/template as world information. This is like a abstract view of your world.
The world information will be a dictionary with keys and values as the following:
adj
: a dictionary of adjacency list containing each node ID as key and value as a list of ID's of children.position
: a dictionary containing each node ID as key and value as a tuple containing position of the node on the world.root
: root node ID.goals
: a list containing node IDs.
These are the mandatory keys, which have to be present in the world information.
Note:
- You only have to pass node IDs which can be a
char
,str
,int
and the library will use it's internal data nodes to create the tree along with world creation. You can access each node and tree information from the library itself. This will also be helpful if you further want to modify/customize the nodes. The keys mention above in the world information are only the necessary key's but there are other keys as well.- The position of each node will be the coordinates. The (0,0) coordinate is you screens top left corner. Please consider drawing the world on a paper before actually writing the world abstract information.
- Please refer the API Reference section for more information.
# tree world information
treeWorldInfo = {
'adj': {
'A': ['B', 'C'],
'B': ['D', 'E'],
'C': ['F', 'G'],
'D': [],
'E': [],
'F': [],
'G': []
},
'position': {
'A': (300, 100),
'B': (150, 200),
'C': (450, 200),
'D': (100, 300),
'E': (200, 300),
'F': (300, 300),
'G': (400, 400)
},
'root': 'A',
'goals': ['G']
}
Remark: you can see that we are only using the abstract information and passing this information to the library. The rest will be taken care by the library like the actual tree data structure creation, world creation etc. this will help the user to save a lot of time and in return help the user to be more creative and allow the user to make complex world easily with only the abstract information.
Create our Hello Tree World¶
Now, we have our world abstract information, we will pass this information to create the tree world object.
# First let's Create a Tree world object!
treeWorld = CreateTreeWorld(worldName="Hello World", worldInfo=treeWorldInfo)
Compile our Hello Tree World¶
since, we are just creating a simple tree world with all the default settings, we are ready to compile our world.
Note: Once you compile the world you can't change the structure of the world. So make sure that you do all the changes before compiling the world.
treeWorld.constructWorld()
Let's see some basic information about our Hello World!¶
you can use a simple print()
statement or you can use the builtin function aboutWorld()
to get the world information as a string.
print(treeWorld)
+-------------------------+-------------+ | Attribute | Value | +-------------------------+-------------+ | World Name | Hello World | | Root Node ID | A | | Goal Nodes | ['G'] | | Width | 3286 | | Height | 1080 | | Node Radius | 20 | | Font Size | 12 | | Font Bold | True | | Font Italic | True | | Node Color | gray | | Goal Color | green | | Line Thickness | 2 | | Arrow Shape | (10, 12, 5) | | Button Background Color | #7FC7D9 | | Button Foreground Color | #332941 | | Text Font | Helvetica | | Text Size | 24 | | Text Weight | bold | | Button Text | Start Agent | +-------------------------+-------------+
print(treeWorld.aboutWorld())
+-------------------------+-------------+ | Attribute | Value | +-------------------------+-------------+ | World Name | Hello World | | Root Node ID | A | | Goal Nodes | ['G'] | | Width | 3286 | | Height | 1080 | | Node Radius | 20 | | Font Size | 12 | | Font Bold | True | | Font Italic | True | | Node Color | gray | | Goal Color | green | | Line Thickness | 2 | | Arrow Shape | (10, 12, 5) | | Button Background Color | #7FC7D9 | | Button Foreground Color | #332941 | | Text Font | Helvetica | | Text Size | 24 | | Text Weight | bold | | Button Text | Start Agent | +-------------------------+-------------+
help(treeWorld)
Help on CreateTreeWorld in module traverseCraft.world object: class CreateTreeWorld(builtins.object) | CreateTreeWorld(worldName: str, worldInfo: dict, radius: int = 20, fontSize: int = 12, fontBold: bool = True, fontItalic: bool = True, nodeColor: str = 'gray', rootColor: str = 'red', goalColor: str = 'green', width: int = 3286, height: int = 1080, lineThickness: int = 2, arrowShape: tuple = (10, 12, 5), buttonBgColor: str = '#7FC7D9', buttonFgColor: str = '#332941', textFont: str = 'Helvetica', textSize: int = 24, textWeight: str = 'bold', buttonText: str = 'Start Agent', logoPath: str = None) | | Class representing a tree world. | | Parameters: | - worldName (str): The name of the world. | - worldInfo (dict): A dictionary containing information about the world. | - 'root' (str): The ID of the root node. | - 'goals' (list): List of goal node IDs. | - 'adj' (dict): Adjacency list representing tree connections. | - 'position' (dict): Dictionary of node positions with node IDs as keys. | - 'edges' (dict, optional): Dictionary of edge information. Default is None. | - 'vals' (dict, optional): Dictionary of node values. Default is None. | - radius (int): The radius of the nodes in the world visualization. Default is 20. | - fontSize (int): The font size of the node labels. Default is 12. | - fontBold (bool): Whether to use bold font for the node labels. Default is True. | - fontItalic (bool): Whether to use italic font for the node labels. Default is True. | - nodeColor (str): The color of the nodes. Default is "gray". | - rootColor (str): The color of the root node. Default is "red". | - goalColor (str): The color of the goal nodes. Default is "green". | - width (int): The width of the world visualization canvas. Default is SCREEN_WIDTH. | - height (int): The height of the world visualization canvas. Default is SCREEN_HEIGHT. | - lineThickness (int): The thickness of the lines connecting the nodes. Default is 2. | - arrowShape (tuple): The shape of the arrows indicating the direction of the edges. Default is (10, 12, 5). | - buttonBgColor (str): The background color of the buttons. Default is "#7FC7D9". | - buttonFgColor (str): The foreground color of the buttons. Default is "#332941". | - textFont (str): The font family of the button text. Default is "Helvetica". | - textSize (int): The font size of the button text. Default is 24. | - textWeight (str): The font weight of the button text. Default is "bold". | - buttonText (str): The text displayed on the buttons. Default is "Start Agent". | - logoPath (str, optional): The file path to the logo image. Default is traverseCraft logo. | | Attributes: | - worldID (str): Class identifier for the tree world. | - _worldName (str): The name of the world. | - _worldInfo (dict): Dictionary containing the world's information. | - _treeRootId (str): The ID of the root node. | - _goalIds (list): List of goal node IDs. | - _position (dict): Dictionary of node positions. | - _width (int): The width of the visualization canvas. | - _height (int): The height of the visualization canvas. | - _radius (int): The radius of the nodes. | - _nodeColor (str): The color of the nodes. | - _rootColor (str): The color of the root node. | - _goalColor (str): The color of the goal nodes. | - _fontSize (int): The font size of the node labels. | - _fontBold (bool): Whether the node labels are bold. | - _fontItalic (bool): Whether the node labels are italic. | - _lineThickness (int): The thickness of the lines connecting the nodes. | - _arrowShape (tuple): The shape of the arrows indicating the direction of the edges. | - _logoPath (str): The file path to the logo image. | - _root (Tk): The root Tkinter object. | - _canvas (Canvas): The canvas object for drawing the world. | - nodeMap (dict): Dictionary mapping node IDs to canvas objects. | - root: The root of the tree data structure. | - _agent: The agent in the world. | - _nodeObj (dict): Dictionary mapping node IDs to node objects. | - _nodeTextObj (dict): Dictionary mapping node IDs to node label objects. | - _buttonBgColor (str): The background color of the buttons. | - _buttonFgColor (str): The foreground color of the buttons. | - _buttonText (str): The text displayed on the buttons. | - _textFont (str): The font family of the button text. | - _textSize (int): The font size of the button text. | - _textWeight (str): The font weight of the button text. | | Methods defined here: | | __init__(self, worldName: str, worldInfo: dict, radius: int = 20, fontSize: int = 12, fontBold: bool = True, fontItalic: bool = True, nodeColor: str = 'gray', rootColor: str = 'red', goalColor: str = 'green', width: int = 3286, height: int = 1080, lineThickness: int = 2, arrowShape: tuple = (10, 12, 5), buttonBgColor: str = '#7FC7D9', buttonFgColor: str = '#332941', textFont: str = 'Helvetica', textSize: int = 24, textWeight: str = 'bold', buttonText: str = 'Start Agent', logoPath: str = None) | Initializes the Tree World. | | __str__(self) | Describes the attributes of the world. | | Parameters: | None | | Returns: | str: The attributes of the world. | | aboutWorld(self) | Describes the attributes of the world. | | Parameters: | None | | Returns: | str: The attributes of the world. | | changeNodeColor(self, nodeId, color) | Changes the color of a node in the tree. | | Parameters: | nodeId (int): The ID of the node to change the color of. | color (str): The new color to set for the node. | | Returns: | None | | changeNodeText(self, nodeId, newText) | Changes the text of a node in the tree. | | Parameters: | nodeId (int): The ID of the node to change the text of. | newText (str): The new text to set for the node. | | Returns: | | constructWorld(self) | Constructs the tree world. | | Parameters: | self (World): The World instance. | | Returns: | None | | getNode(self, nodeId) | Returns the pointer to the node with the given nodeId. | | Parameters: | nodeId: The ID of the node to retrieve the pointer for. | | Returns: | Node: The pointer to the node with the given nodeId. | | setAgent(self, agent) | Set the agent for the world. | | Parameters: | agent (Agent): The agent to be set. | | Returns: | None | | showWorld(self) | Displays the world. | | Parameters: | None | Returns: | None | | summary(self) | Generates a summary of the world. | | Parameters: | None | | Returns: | str: The summary of the world. | | ---------------------------------------------------------------------- | Data descriptors defined here: | | __dict__ | dictionary for instance variables (if defined) | | __weakref__ | list of weak references to the object (if defined) | | ---------------------------------------------------------------------- | Data and other attributes defined here: | | worldID = 'TREEWORLD'
Let's create our agent which will interact with the world.¶
here also we will create a simple tree agent with the default settings.
treeAgent = TreeAgent(agentName="Tree Agent", world=treeWorld)
Let's see some basic information about our tree Agent
.¶
you can use a simple print()
statement or you can use the builtin function aboutAgent()
to get the agent information as a string.
print(treeAgent)
+--------------+-------------+ | Attribute | Value | +--------------+-------------+ | Agent Name | Tree Agent | | Agent Color | blue | | World Name | Hello World | | World ID | TREEWORLD | | Root Node ID | A | +--------------+-------------+
print(treeAgent.aboutAgent())
+--------------+-------------+ | Attribute | Value | +--------------+-------------+ | Agent Name | Tree Agent | | Agent Color | blue | | World Name | Hello World | | World ID | TREEWORLD | | Root Node ID | A | +--------------+-------------+
Connect Our Agent with the World¶
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.
treeWorld.setAgent(treeAgent)
Algorithm¶
Now, we have connected the agent with the world, but we did not told the agent what to do in the world.
The agent have a method setAlgorithmCallBack()
which takes a function as a argument.
This function will be run during the simulation.
Note: Make sure that the function you are passing in the
setAlgorithmCallBack()
method does not take any argument.
Let's first create our function which will tell the agent what to do.¶
We will use the moveAgent()
method of the agent class to move the agent.
We will start from node 'A', which is the root node as well as the start position of the agent by default and we will move the agent in the following manner:
'A' -> 'B' -> 'D' -> 'B' -> 'E' -> 'B' -> 'A' -> 'C' -> 'G'
def whatToDo():
print("I am a Tree Agent and I am going to move around the world!")
treeAgent.moveAgent('B')
treeAgent.moveAgent('D')
treeAgent.moveAgent('B')
treeAgent.moveAgent('E')
treeAgent.moveAgent('B')
treeAgent.moveAgent('A')
treeAgent.moveAgent('C')
treeAgent.moveAgent('G')
print("I am done moving around the world!")
We are ready with our algorithm¶
Lets set the algorithm to tell the agent what to do.
treeAgent.setAlgorithmCallBack(whatToDo)
Display the world and Start the Simulation!¶
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.
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.
treeWorld.showWorld()
I am a Grid Agent and I am going to move around the world! I am done moving around the world!
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 tree agent object creation.
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
.
Let's see the summary¶
The agent and the world keep some records, that we can generate and see.
The Agent have information about the time taken to run the whole simulation.¶
We can see this information using the summary
method.
print(treeAgent.summary())
+--------------+---------------------------+ | Attribute | Value | +--------------+---------------------------+ | Start Time | Wed, 19 Jun 2024 18:13:00 | | End Time | Wed, 19 Jun 2024 18:13:08 | | Elapsed Time | 8.023 sec | +--------------+---------------------------+
The World have information about the visited count after the whole simulation.¶
We can see this information using the summary
method.
print(treeWorld.summary())
+---------+------------------+ | Node ID | Number of Visits | +---------+------------------+ | A | 2 | | B | 3 | | C | 1 | | D | 1 | | E | 1 | | F | 0 | | G | 1 | +---------+------------------+
help(treeAgent)
Help on TreeAgent in module traverseCraft.agent object: class TreeAgent(builtins.object) | TreeAgent(world, agentName: str, agentColor: str = 'blue', heatMapView: bool = True, heatMapColor: str = '#FFA732', heatGradient: float = 0.05) | | The Tree Agent class. | | Parameters: | world (CreateTreeWorld): The world object that the agent belongs to. | agentName (str): The name of the agent. | agentColor (str, optional): The color of the agent. Defaults to "blue". | heatMapView (bool, optional): Flag indicating whether to enable heat map view. Defaults to True. | heatMapColor (str, optional): The color of the heat map. Defaults to "#FFA732". | heatGradient (float, optional): The gradient of the heat map. Defaults to 0.05. | | Attributes: | _worldObj (CreateTreeWorld): The tree world object. | _worldID (str): The ID of the world. | _root (Tk): The root Tkinter object from the tree world. | _agentName (str): The name of the agent. | _agentColor (str): The color of the agent. | _heatMapView (bool): Indicates if the heat map view is enabled. | _heatMapColor (str): The color of the heat map. | _heatMapBaseColor (str): The base color of the heat map. | _heatGradient (float): The gradient value for the heat map. | _treeRoot (TreeNode): The root node of the tree. | _currentNode (TreeNode): The current node the agent is on. | algorithmCallBack (function): Callback function for the agent's algorithm. | _startTime (float): The start time of the agent. | _endTime (float): The end time of the agent. | | Methods defined here: | | __init__(self, world, agentName: str, agentColor: str = 'blue', heatMapView: bool = True, heatMapColor: str = '#FFA732', heatGradient: float = 0.05) | Initialize self. See help(type(self)) for accurate signature. | | __str__(self) | Describes the attributes of the world. | | Parameters: | None | | Returns: | function(): The attributes of the world. | | aboutAgent(self) | Prints information about the agent. | | Parameters: | None | | Returns: | str: A string containing information about the agent. | | checkGoalState(self, nodeId) | Check if the given node is a goal state. | | Parameters: | - nodeId: The node Id to be checked. | | Returns: | - True if the node is a goal state, False otherwise. | | getHeatMapColor(self, value: float) | Returns the color for a given value on a heat map. | | Parameters: | value (float): The value to map to a color on the heat map. | | Returns: | tuple: The RGB color value for the given value on the heat map. | | moveAgent(self, nodeId, delay: int = 1) | Moves the agent to the specified node. | | Args: | nodeId: The node Id to which the agent should be moved. | delay (optional): The delay (in seconds) before moving to the next node. Default is 1 second. | | Returns: | bool: True if the agent was successfully moved to the node, False otherwise. | | runAlgorithm(self) | Executes the algorithm callback function. | | Raises: | ValueError: If the algorithm callback function is not set. | | setAlgorithmCallBack(self, algorithmCallBack) | Set the callback function for the algorithm. | | Parameters: | algorithmCallBack (function): The callback function to be set. | | Returns: | None | | summary(self) | Returns a summary of the agent run. | | Returns: | str: A summary of the agent run. | | ---------------------------------------------------------------------- | Data descriptors defined here: | | __dict__ | dictionary for instance variables (if defined) | | __weakref__ | list of weak references to the object (if defined)
This covers the basic of how to create a simple Tree World and Tree Agent. How to connect the created agent with the world and how to run a simple algorithm to simulate the agent on the world.
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.
Thanks!