Repository: ARgorithm/toolkit (language: python)

Issue:
Implementing Map/Dict functionality with ARgorithmToolkit objects.
To implement a lot of algorithms, a dict or hashmap maybe a necessary Data-structure. It'll require some form of generics or interface classes to use as key-value pairs, to ensure that the correct data is being written into the states, and object references aren't lost.




Discussion / hints:
# class serializability and storing object id in state

- within `state_def`
make object id a compulsory part of metadata

- all ARgorithmToolkit classes to be made JSON serialisable.
refer [this](https://stackoverflow.com/questions/3768895/how-to-make-a-class-json-serializable) for more info
We can do this easily by creating our own `ARgorithmToolkit.utils.Encoder` which can parse StateSet into a JSON and convert ARgorithmToolkit class objects into strings/objects containing reference to the id of the ARgorithmToolkit object used in body

lets say a `ARgorithmToolkit.Array` can be serialised into a string like 
```Json
"$argorithm_array_{id}"
``` 
or into an object like
```json
{
     "argorithm_object" : {
           "type" : "Array",
           "id" : "<whatever id>"
     }
}
```

Fix patch:
diff --git a/.pylintrc b/.pylintrc
index f1225ac..c02f919 100644
--- a/.pylintrc
+++ b/.pylintrc
@@ -490,16 +490,16 @@ min-similarity-lines=4
 [DESIGN]
 
 # Maximum number of arguments for function / method.
-max-args=5
+max-args=10
 
 # Maximum number of attributes for a class (see R0902).
-max-attributes=7
+max-attributes=10
 
 # Maximum number of boolean expressions in an if statement (see R0916).
 max-bool-expr=5
 
 # Maximum number of branch for function / method body.
-max-branches=12
+max-branches=15
 
 # Maximum number of locals for function / method body.
 max-locals=15
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 7b71755..d6aad2f 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -3,5 +3,5 @@
     "yaml.schemas": {
         "./designs/design.json": ".design.yml"
     },
-    "python.linting.pylintEnabled": true
+    "python.linting.pylintEnabled": false
 }
diff --git a/ARgorithmToolkit/__init__.py b/ARgorithmToolkit/__init__.py
index a82702b..af69ce7 100644
--- a/ARgorithmToolkit/__init__.py
+++ b/ARgorithmToolkit/__init__.py
@@ -15,3 +15,5 @@
 from ARgorithmToolkit.string import String
 from ARgorithmToolkit.linkedlist import LinkedList,LinkedListNode,ForwardList
 from ARgorithmToolkit.doublylinkedlist import DoublyLinkedList,DoublyLinkedListNode,List
+from ARgorithmToolkit.map import Map
+from ARgorithmToolkit.set import Set
diff --git a/ARgorithmToolkit/__main__.py b/ARgorithmToolkit/__main__.py
index 19f4824..928a9d2 100644
--- a/ARgorithmToolkit/__main__.py
+++ b/ARgorithmToolkit/__main__.py
@@ -3,4 +3,4 @@
 
 if __name__ == "__main__":
     from ARgorithmToolkit.cli import app
-    app()
\ No newline at end of file
+    app()
diff --git a/ARgorithmToolkit/array.py b/ARgorithmToolkit/array.py
index 21aab00..0d19535 100644
--- a/ARgorithmToolkit/array.py
+++ b/ARgorithmToolkit/array.py
@@ -9,7 +9,8 @@ class can directly be imported from the ARgorithmToolkit library without having
 """
 
 import numpy as np
-from ARgorithmToolkit.utils import State, StateSet, ARgorithmError
+from ARgorithmToolkit.utils import State, StateSet, ARgorithmError, ARgorithmStructure
+from ARgorithmToolkit.encoders import serialize
 
 def check_dimensions(data):
     """This function is an internal function that helps verify the dimensions
@@ -41,11 +42,12 @@ class ArrayState:
 
     Attributes:
 
-        name (str) : Name of the variable for whom we are generating states
+        name (str) : Name of the object for which the states are generated
+        _id (str) : id of the object for which the states are generated
     """
-    def __init__(self,name):
+    def __init__(self,name,_id):
         self.name = name
-
+        self._id = _id
 
     def array_declare(self,body,comments=""):
         """Generates the `array_declare` state when an instance of Array class
@@ -60,6 +62,7 @@ def array_declare(self,body,comments=""):
         """
         state_type = "array_declare"
         state_def = {
+            "id": self._id,
             "variable_name" : self.name,
             "body" : body.tolist()
         }
@@ -85,6 +88,7 @@ def array_iter(self,body,index,value=None,last_value=None,comments=""):
         """
         state_type = "array_iter"
         state_def = {
+            "id" : self._id,
             "variable_name" : self.name,
             "body" : body.tolist(),
             "index" : index
@@ -112,6 +116,7 @@ def array_swap(self,body,indexes,comments=""):
         """
         state_type = "array_swap"
         state_def = {
+            "id" : self._id,
             "variable_name" : self.name,
             "body" : body.tolist(),
             "index1" : indexes[0],
@@ -137,6 +142,7 @@ def array_compare(self,body,indexes,comments=""):
         """
         state_type = "array_compare"
         state_def = {
+            "id" : self._id,
             "variable_name" : self.name,
             "body" : body.tolist(),
             "index1" : indexes[0],
@@ -171,7 +177,8 @@ def __next__(self):
         self._index += 1
         return v
 
-class Array:
+@serialize
+class Array(ARgorithmStructure):
     """The Array class used to emulate multidimensional arrays that can be
     rendered in the ARgorithm Application as series of blocks.
 
@@ -228,7 +235,7 @@ class Array:
     def __init__(self, name:str, algo:StateSet, data=None, shape=None, fill=0, dtype=int, comments=""):
         try:
             assert isinstance(name,str)
-            self.state_generator = ArrayState(name)
+            self.state_generator = ArrayState(name, str(id(self)))
         except Exception as ex:
             raise ARgorithmError('Give valid name to data structure') from ex
         try:
@@ -347,7 +354,7 @@ def __iter__(self):
             >>> [x for x in arr]
             [[1,2,3],[4,5,6]]
         """
-        return iter(self.body)
+        return ArrayIterator(self)
 
     def compare(self,index1,index2,func=None,comments=""):
         """compares elements at 2 indexes of array.
diff --git a/ARgorithmToolkit/cli.py b/ARgorithmToolkit/cli.py
index e3ab5bb..4ba46c1 100644
--- a/ARgorithmToolkit/cli.py
+++ b/ARgorithmToolkit/cli.py
@@ -1,4 +1,6 @@
 # pylint: disable=no-self-use
+# pylint: disable=too-many-statements
+# pylint: disable=raise-missing-from
 """CLI tool for ARgorithm made using typer
 """
 import os
@@ -7,6 +9,9 @@
 import requests
 import typer
 from halo import Halo
+import ARgorithmToolkit
+from ARgorithmToolkit.parser import ARgorithmConfig,ValidationError,input_data
+from ARgorithmToolkit.security import injection_check,execution_check
 
 CLOUD_URL = "https://argorithm.el.r.appspot.com"
 CACHE_DIR = typer.get_app_dir("ARgorithm")
@@ -53,7 +58,7 @@ def menuitem(self,argorithm):
         typer.secho(f"\tby {argorithm['maintainer']}",fg=typer.colors.CYAN)
         typer.echo("\tParameters")
         for key in argorithm['parameters']:
-            typer.echo(f"\t\t{key} : {argorithm['parameters'][key]}")
+            typer.echo(f"\t\t{key} : {argorithm['parameters'][key]['description']}")
 
     def state(self,states):
         """pretty print states
@@ -164,14 +169,11 @@ def login_prompt(self):
             raise typer.Abort()
         if rq.status_code == 404:
             msg.warn("User not found","please enter valid email")
-            raise typer.Exit(1)
-        if rq.status_code == 500:
+        elif rq.status_code == 500:
             msg.fail("Server error","contact developer")
-            raise typer.Exit(2)
-        if rq.status_code == 401:
+        elif rq.status_code == 401:
             msg.warn("incorrect password")
-            raise typer.Exit(1)
-        if rq.status_code == 200:
+        elif rq.status_code == 200:
             msg.good("logged in successfully","credentials saved in cache")
             token = json.loads(rq.content)['access_token']
             with open(self.credfile,'w+') as cred:
@@ -210,12 +212,13 @@ def auth_check(self):
                     rq = requests.get(url)
             except requests.RequestException as rqe:
                 msg.fail("Connection failed",str(rqe))
-                raise typer.Abort()    
+                raise typer.Abort()
             if rq.status_code == 200:
                 return True
             return False
         except Exception as ex:
             msg.warn("authentication error",str(ex))
+            raise typer.Abort()
 
 authmanager = AuthManager()
 
@@ -241,46 +244,38 @@ def name_check(value:str):
 
 @app.command()
 def init(
-        name:str = typer.Argument(...,help="The name given to the argorithm [A-Za-z_]",callback=name_check)
+        name:str = typer.Argument(...,help="The name given to the argorithm [A-Za-z_]",callback=name_check),
+        create_config:bool = typer.Option(False,'--config','-c',help="creates blank config file as well",show_default=False)
     ):
     """
     Create Blank code template and config template for ARgorithm
     """
     typer.echo(f"Creating empty template for {name}")
 
-    filename = f"{name}.py"
-    with open(filename , "w") as codefile:
-        code_starter = """
-import ARgorithmToolkit
+    with open(os.path.join(ARgorithmToolkit.__path__[0],'data/template.py',),'rb') as template:
+        starter = template.read()
 
-def run(**kwargs):
-    algo = ARgorithmToolkit.StateSet()
-
-    #
-    # Your code
-    #
-
-    return algo
-
-        """
-        codefile.write(code_starter)
-
-    config = {
-        "argorithmID" : name,
-        "file" : name+".py",
-        "function" : "run",
-        "parameters" : {},
-        "default" : {},
-        "description" : ""
-    }
-    config_file=f"{name}.config.json"
-    with open(config_file, "w") as configfile:
-        json.dump(config,configfile)
+    filename = f"{name}.py"
+    with open(filename , "wb") as codefile:
+        codefile.write(starter)
+
+    if create_config:
+        config = {
+            "argorithmID" : name,
+            "file" : name+".py",
+            "function" : "run",
+            "parameters" : {},
+            "default" : {},
+            "description" : ""
+        }
+        config_file=f"{name}.config.json"
+        with open(config_file, "w") as configfile:
+            json.dump(config,configfile)
 
     msg.good("Template generated","refer documentation at https://argorithm.github.io/toolkit/ to learn how to use it\nchech out examples at https://github.com/ARgorithm/toolkit/tree/master/examples")
 
 @app.command()
-def configure():
+def connect():
     """
     Connect to your endpoint
     """
@@ -294,48 +289,72 @@ def autocomplete(incomplete:str):
     l = len(incomplete)
     for filename in files:
         if filename[:l] == incomplete and filename[-3:] == '.py':
-            res.append(filename[:-4])
+            res.append(filename[:-3])
     return res
 
 def file_reader(filename):
     """finds anf checks argorithm files"""
     directory = os.getcwd()
     if os.path.isfile( os.path.join(directory,filename+".py")):
-        if os.path.isfile( os.path.join(directory , f"{filename}.config.json") ):
-            pass
-        else:
-            msg.warn(f"cant find {filename}.config.json")
+        try:
+            data = ARgorithmConfig(f"{filename}.config.json")
+            injection_check(os.path.join(directory,filename+".py"))
+        except FileNotFoundError:
+            msg.warn("config missing",f"you can use edit the {filename}.config.json \nor use CLI based config generator")
+            raise typer.Exit()
+        except ValidationError:
+            msg.warn("config file is not configured properly","try the configure command to fix it \ncheck out docs for more info")
+            raise typer.Exit(1)
+        except ARgorithmToolkit.ARgorithmError:
+            msg.warn("possible code injection","- remove imports other than ARgorithmToolkit\n- rename user-defined objects,classes and functions")
             raise typer.Exit(1)
     else:
         msg.warn(f"{filename}.py not found")
         raise typer.Exit(1)
-    msg.good('files found')
-
-    required_tags = {
-        "argorithmID" : filename,
-        "file" : filename+".py",
-        "function" : "run",
-        "parameters" : {},
-        "default" : {},
-        "description" : ""
-    }
-
-    with open(os.path.join(directory , f"{filename}.config.json") , 'r') as configfile:
-        data = json.load(configfile)
-        for key in required_tags:
-            if key not in data:
-                msg.warn(f"please check {filename}.config.json {key} is missing")
-                raise typer.Exit(1)
-        for key in data:
-            if key not in required_tags:
-                msg.warn(f"please check {filename}.config.json {key} is uneccessary")
-                raise typer.Exit(1)
-            if type(data[key]) != type(required_tags[key]):
-                msg.warn(f"please check {key} in {filename}.config.json")
-                raise typer.Exit(1)
-
     msg.good("Files Verified")
-    return data
+    try:
+        execution_check(os.path.join(directory,filename+".py"),data.config)
+    except AssertionError:
+        msg.warn('Testing Failed','Function should return ARgorithmToolkit.StateSet object')
+        raise typer.Exit(1)
+    except Exception:
+        msg.warn('Testing Failed','ARgorithm execution with example kwargs failed')
+        raise typer.Exit(1)
+    msg.good("Files Tested")
+    return data.config
+
+@app.command()
+def configure(filename:str=typer.Argument(... , help="name of argorithm" , autocompletion=autocomplete)
+    ):
+    """Starts CLI config generator"""
+    codefile = filename.split('.')[0] + ".py"
+    if not os.path.isfile(os.path.join(os.getcwd(),codefile)):
+        msg.warn("Python file not found",'use the init command first')
+        raise typer.Abort()
+    filepath = filename.split('.')[0] + ".config.json"
+    try:
+        existing_config = {
+            "argorithmID" : filename,
+            "file" : filename+".py",
+            "function" : "run",
+            "parameters" : {},
+            "default" : {},
+            "description" : ""
+        }
+        if os.path.isfile( os.path.join(os.getcwd() , f"{filepath}") ):
+            with open(os.path.join(os.getcwd(), f"{filepath}") , 'r') as configfile:
+                existing_config = json.load(configfile)
+            os.remove(os.path.join(os.getcwd() , f"{filepath}"))
+        ARgorithmConfig(filepath)
+    except FileNotFoundError:
+        msg.warn("Operation cancelled by user")
+        with open(os.path.join(os.getcwd(), f"{filepath}") , 'w') as configfile:
+            json.dump(existing_config,configfile)
+        typer.Abort()
+    except Exception:
+        msg.fail("Some error occured, try again")
+        with open(os.path.join(os.getcwd(), f"{filepath}") , 'w') as configfile:
+            json.dump(existing_config,configfile)
 
 @app.command()
 def submit(
@@ -453,14 +472,12 @@ def list_argorithms():
 @app.command()
 def test(
     argorithm_id:str = typer.Argument(... , help="argorithmID of function to be called. If not passed then menu will be presented"),
-    output:bool = typer.Option(False,'--output','-o',help="print results in json format",show_default=False)
-    # user_input:bool = typer.Option(False,'--user-input','-u',help="if present, parses input from user",show_default=False)
+    output:bool = typer.Option(False,'--output','-o',help="print results in json format",show_default=False),
+    user_input:bool = typer.Option(False,'--user-input','-u',help="if present, takes input from user",show_default=False)
     ):
     """test argorithms stored in server
     """
     params = search(argorithm_id,show=not output)
-    # if user_input:
-    #     pass
     header=None
     if authmanager.auth_check():
         token = authmanager.get_token()
@@ -470,6 +487,8 @@ def test(
         "argorithmID" : params["argorithmID"],
         "parameters" : params["example"]
     }
+    if user_input:
+        data["parameters"] = input_data(params["parameters"])
     url = settings.get_endpoint()+"/argorithms/run"
     try:
         with Halo(text='Connecting', spinner='dots'):
diff --git a/ARgorithmToolkit/data/config.schema.json b/ARgorithmToolkit/data/config.schema.json
new file mode 100644
index 0000000..ca3a06d
--- /dev/null
+++ b/ARgorithmToolkit/data/config.schema.json
@@ -0,0 +1,144 @@
+{
+    "$schema": "http://json-schema.org/draft-07/schema#",
+    "title": "ARgorithm config",
+    "description": "ARgorithm configuration file schema",
+    "type" : "object",
+    "properties" : {
+        "argorithmID" : {
+            "type" : "string"
+        },
+        "file" : {
+            "type" : "string"
+        },
+        "function" : {
+            "type" : "string"
+        },
+        "parameters" : {
+            "type" : "object",
+            "patternProperties" : {
+                "^[a-zA-Z].*$":{
+                    "type" : "object",
+                    "anyOf" : [
+                        {
+                            "properties" : {
+                                "type" : {
+                                    "const" : "INT"
+                                },
+                                "description" : {
+                                    "type" : "string"
+                                },
+                                "start" : {
+                                    "type" : "integer"
+                                },
+                                "end" : {
+                                    "type" : "integer"
+                                }
+                            },
+                            "required" : ["type","description"],
+                            "additionalProperties" : false
+                        },
+                        {
+                            "properties" : {
+                                "type" : {
+                                    "const" : "FLOAT"
+                                },
+                                "description" : {
+                                    "type" : "string"
+                                },
+                                "start" : {
+                                    "type" : "number"
+                                },
+                                "end" : {
+                                    "type" : "number"
+                                }
+                            },
+                            "required" : ["type","description"],
+                            "additionalProperties" : false
+                        },
+                        {
+                            "properties" : {
+                                "type" : {
+                                    "const" : "STRING"
+                                },
+                                "description" : {
+                                    "type" : "string"
+                                },
+                                "size" : {
+                                    "type" : ["integer","string"]
+                                }
+                            },
+                            "required" : ["type","description"],
+                            "additionalProperties" : false
+                        },
+                        {
+                            "properties" : {
+                                "type" : {
+                                    "const" : "ARRAY"
+                                },
+                                "description" : {
+                                    "type" : "string"
+                                },
+                                "size" : {
+                                    "type" : ["integer","string"]
+                                },
+                                "item-type" : {
+                                    "type" : "string",
+                                    "enum" : [
+                                        "INT",
+                                        "FLOAT",
+                                        "STRING"
+                                    ]
+                                }
+                            },
+                            "required" : ["type","description","item-type"],
+                            "additionalProperties" : false
+                        },
+                        {
+                            "properties" : {
+                                "type" : {
+                                    "const" : "ARRAY"
+                                },
+                                "description" : {
+                                    "type" : "string"
+                                },
+                                "row" : {
+                                    "type" : ["integer","string"]
+                                },
+                                "col" : {
+                                    "type" : ["integer","string"]
+                                },
+                                "item-type" : {
+                                    "type" : "string",
+                                    "enum" : [
+                                        "INT",
+                                        "FLOAT",
+                                        "STRING"
+                                    ]
+                                }
+                            },
+                            "required" : ["type","description","col","row","item-type"],
+                            "additionalProperties" : false
+                        }
+                    ]
+                }
+            },
+            "additionalProperties" : false
+        },
+        "description" : {
+            "type" : "string"
+        },
+        "example" : {
+            "type" : "object",
+            "additionalProperties" : true
+        }
+    },
+    "required" : [
+        "argorithmID" ,
+        "file" ,
+        "function" ,
+        "description",
+        "parameters",
+        "example"
+    ],
+    "additionalProperties" : false
+}
\ No newline at end of file
diff --git a/ARgorithmToolkit/data/template.py b/ARgorithmToolkit/data/template.py
new file mode 100644
index 0000000..7f199e3
--- /dev/null
+++ b/ARgorithmToolkit/data/template.py
@@ -0,0 +1,10 @@
+import ARgorithmToolkit
+
+def run(**kwargs):
+    algo = ARgorithmToolkit.StateSet()
+
+    #
+    # Your code
+    #
+
+    return algo
diff --git a/ARgorithmToolkit/doublylinkedlist.py b/ARgorithmToolkit/doublylinkedlist.py
index eb62b7d..00d615e 100644
--- a/ARgorithmToolkit/doublylinkedlist.py
+++ b/ARgorithmToolkit/doublylinkedlist.py
@@ -15,7 +15,8 @@
 
 """
 
-from ARgorithmToolkit.utils import State, StateSet, ARgorithmError
+from ARgorithmToolkit.utils import ARgorithmHashable, ARgorithmStructure, State, StateSet, ARgorithmError
+from ARgorithmToolkit.encoders import serialize
 
 class DoublyLinkedListNodeState:
     """This class is used to generate states for various actions performed on
@@ -23,11 +24,13 @@ class DoublyLinkedListNodeState:
 
     Attributes:
 
-        name (str) : Name of the variable for whom we are generating states
+        name (str) : Name of the object for which states are generated
+        _id (str) : id of the object for which states are generated
     """
 
-    def __init__(self,name:str):
+    def __init__(self,name:str,_id:str):
         self.name = name
+        self._id = _id
 
     def dllnode_declare(self,value,next_node,prev_node,comments=""):
         """Generates the `dllnode_declare` state when a new node is created.
@@ -43,6 +46,7 @@ def dllnode_declare(self,value,next_node,prev_node,comments=""):
         """
         state_type = "dllnode_declare"
         state_def = {
+            "id" : self._id,
             "variable_name" : self.name,
             "value" : value,
             "next" : next_node.name if next_node else "none",
@@ -70,6 +74,7 @@ def dllnode_iter(self,value,next_node,prev_node,last_value=None,comments=""):
         """
         state_type = "dllnode_iter"
         state_def = {
+            "id" : self._id,
             "variable_name" : self.name,
             "value" : value,
             "next" : next_node.name if next_node else "none",
@@ -97,6 +102,7 @@ def dllnode_next(self,value,next_node,prev_node,last_next,comments=""):
         """
         state_type = "dllnode_next"
         state_def = {
+            "id" : self._id,
             "variable_name" : self.name,
             "value" : value,
             "next" : next_node.name if next_node else "none",
@@ -123,6 +129,7 @@ def dllnode_prev(self,value,next_node,prev_node,last_prev,comments=""):
         """
         state_type = "dllnode_prev"
         state_def = {
+            "id" : self._id,
             "variable_name" : self.name,
             "value" : value,
             "next" : next_node.name if next_node else "none",
@@ -147,6 +154,7 @@ def dllnode_delete(self,comments=""):
         """
         state_type = "dllnode_delete"
         state_def = {
+            "id" : self._id,
             "variable_name" : self.name,
         }
         return State(
@@ -155,7 +163,8 @@ def dllnode_delete(self,comments=""):
             comments=comments
         )
 
-class DoublyLinkedListNode:
+@serialize
+class DoublyLinkedListNode(ARgorithmStructure, ARgorithmHashable):
     """The DoublyLinkedListNode class is an implementation of a Linked list
     Node for which we store states. Unlike other data structure classes, in
     which we have to give a name to the instance, we dont have to provide name
@@ -181,14 +190,15 @@ class DoublyLinkedListNode:
     """
 
     def __init__(self,algo:StateSet,value=None,comments=""):
-        self.name = id(self)
+        self.name = str(id(self))
+        self._id = str(id(self))
         try:
             assert isinstance(algo,StateSet)
             self.algo = algo
         except AssertionError as e:
             raise ARgorithmError("algo should be of type StateSet") from e
 
-        self.state_generator = DoublyLinkedListNodeState(self.name)
+        self.state_generator = DoublyLinkedListNodeState(self.name, self._id)
 
         self._flag = False
         self.value = value
@@ -271,9 +281,11 @@ class DoublyLinkedListState:
     Attributes:
 
         name (str) : Name of the variable for whom we are generating states
+        _id (str) : id of the variable for whom we are generating states
     """
-    def __init__(self,name:str):
+    def __init__(self,name:str,_id:str):
         self.name = name
+        self._id = _id
 
     def dll_declare(self,head,tail,comments=""):
         """Generates the `dll_declare` state when a new linked list is created.
@@ -288,6 +300,7 @@ def dll_declare(self,head,tail,comments=""):
         """
         state_type = "dll_declare"
         state_def = {
+            "id" : self._id,
             "variable_name" : self.name,
             "head" : head.name if head else "none",
             "tail" : tail.name if tail else "none"
@@ -298,7 +311,7 @@ def dll_declare(self,head,tail,comments=""):
             comments=comments
         )
 
-    def dll_head(self,head,tail,comments=""):
+    def dll_head(self,head,tail,last_head=None,comments=""):
         """Generates the `dll_head` state when linked list head is changed.
 
         Args:
@@ -311,17 +324,20 @@ def dll_head(self,head,tail,comments=""):
         """
         state_type = "dll_head"
         state_def = {
+            "id" : self._id,
             "variable_name" : self.name,
             "head" : head.name if head else "none",
             "tail" : tail.name if tail else "none"
         }
+        if not (last_head is None):
+            state_def['last_head'] = last_head
         return State(
             state_type=state_type,
             state_def=state_def,
             comments=comments
         )
 
-    def dll_tail(self,head,tail,comments=""):
+    def dll_tail(self,head,tail,last_tail=None,comments=""):
         """Generates the `dll_tail` state when linked list tail is changed.
 
         Args:
@@ -334,17 +350,21 @@ def dll_tail(self,head,tail,comments=""):
         """
         state_type = "dll_tail"
         state_def = {
+            "id" : self._id,
             "variable_name" : self.name,
             "head" : head.name if head else "none",
             "tail" : tail.name if tail else "none"
         }
+        if not(last_tail is None):
+            state_def['last_tail'] = last_tail
         return State(
             state_type=state_type,
             state_def=state_def,
             comments=comments
         )
 
-class DoublyLinkedList:
+@serialize
+class DoublyLinkedList(ARgorithmStructure, ARgorithmHashable):
     """The DoublyLinkedList class is used to just store the head of the linked
     list.
 
@@ -371,12 +391,13 @@ def __init__(self,name:str,algo:StateSet,head=None,comments=""):
 
         assert isinstance(name,str) , ARgorithmError("Name should be of type string")
         self.name = name
+        self._id = str(id(self))
         try:
             assert isinstance(algo,StateSet)
             self.algo = algo
         except AssertionError as e:
             raise ARgorithmError("algo should be of type StateSet") from e
-        self.state_generator = DoublyLinkedListState(self.name)
+        self.state_generator = DoublyLinkedListState(self.name, self._id)
 
         if head:
             assert self.algo == head.algo, ARgorithmError("The head node belongs to a different StateSet")
@@ -398,12 +419,18 @@ def __setattr__(self,key,value):
         """
         if key in ['head','tail'] and value:
             assert isinstance(value,DoublyLinkedListNode) , ARgorithmError("next should be of type None or DoublyLinkedListNode")
+        last_head = None
+        last_tail = None
+        if key == 'head' and self._flag:
+            last_head = self.head._id if self.head else "none"
+        elif key == 'tail' and self._flag:
+            last_tail = self.tail._id if self.tail else "none"
         self.__dict__[key] = value
         if key == 'head' and self._flag:
-            state = self.state_generator.dll_head(self.head,self.tail,"head pointer shifts")
+            state = self.state_generator.dll_head(self.head,self.tail,last_head=last_head,comments="head pointer shifts")
             self.algo.add_state(state)
         if key == 'tail' and self._flag:
-            state = self.state_generator.dll_tail(self.head,self.tail,"tail pointer shifts")
+            state = self.state_generator.dll_tail(self.head,self.tail,last_tail=last_tail,comments="tail pointer shifts")
             self.algo.add_state(state)
 
     def __str__(self):
diff --git a/ARgorithmToolkit/encoders.py b/ARgorithmToolkit/encoders.py
new file mode 100644
index 0000000..abe40e3
--- /dev/null
+++ b/ARgorithmToolkit/encoders.py
@@ -0,0 +1,38 @@
+"""For support of nested ARgorithm Classes, this module provides with a Encoder that stores the reference to ARgorithm Object
+whenever an ARgorithm Class object is serialized in the StateSet (which only happens when we nest one ARgorithm Class in another)
+"""
+import inspect
+from json import JSONEncoder
+import ARgorithmToolkit
+
+def serialize(cls):
+    """Decorator to make classes serializable
+    """
+    def to_json(self):
+        """Creates a string representing a reference to ARgorithmObject for use in application
+        """
+        class_name = type(self).__name__
+        obj_id = id(self)
+        return f"$ARgorithmToolkit.{class_name}:{obj_id}"
+    setattr(cls,'to_json',to_json)
+    return cls
+
+class StateEncoder(JSONEncoder):
+    """The custon Encoder to be used to convert StateSet into JSON. Supports ARgorithm Classes as well
+    """
+    def default(self, o):
+        """The function called when an object has to be serialized
+
+        Args:
+            o ([type]): The object to be serialized
+        """
+        classes = inspect.getmembers(ARgorithmToolkit,inspect.isclass)
+        classes = tuple([x for _,x in classes])
+        if isinstance(ARgorithmToolkit.Variable,classes) :
+            return super().default(o.value)
+        elif isinstance(o, classes):
+            try:
+                return o.to_json()
+            except Exception as ex:
+                raise TypeError("Unserializable ARgorithm class",) from ex
+        return super().default(o)
diff --git a/ARgorithmToolkit/linkedlist.py b/ARgorithmToolkit/linkedlist.py
index 1af4dbf..358d6b5 100644
--- a/ARgorithmToolkit/linkedlist.py
+++ b/ARgorithmToolkit/linkedlist.py
@@ -15,7 +15,8 @@
 
 """
 
-from ARgorithmToolkit.utils import State, StateSet, ARgorithmError
+from ARgorithmToolkit.utils import ARgorithmHashable, ARgorithmStructure, State, StateSet, ARgorithmError
+from ARgorithmToolkit.encoders import serialize
 
 class LinkedListNodeState:
     """This class is used to generate states for various actions performed on
@@ -24,10 +25,12 @@ class LinkedListNodeState:
     Attributes:
 
         name (str) : Name of the variable for whom we are generating states
+        _id (str) : id of the variable for whom we are generating states
     """
 
-    def __init__(self,name:str):
+    def __init__(self,name:str,_id:str):
         self.name = name
+        self._id = _id
 
     def llnode_declare(self,value,_next,comments=""):
         """Generates the `llnode_declare` state when a new node is created.
@@ -42,6 +45,7 @@ def llnode_declare(self,value,_next,comments=""):
         """
         state_type = "llnode_declare"
         state_def = {
+            "id" : self._id,
             "variable_name" : self.name,
             "value" : value,
             "next" : _next.name if _next else "none"
@@ -66,6 +70,7 @@ def llnode_iter(self,value,_next,last_value=None,comments=""):
         """
         state_type = "llnode_iter"
         state_def = {
+            "id" : self._id,
             "variable_name" : self.name,
             "value" : value,
             "next" : _next.name if _next else "none"
@@ -91,6 +96,7 @@ def llnode_next(self,value,_next,last_next,comments=""):
         """
         state_type = "llnode_next"
         state_def = {
+            "id" : self._id,
             "variable_name" : self.name,
             "value" : value,
             "next" : _next.name if _next else "none",
@@ -113,6 +119,7 @@ def llnode_delete(self,comments=""):
         """
         state_type = "llnode_delete"
         state_def = {
+            "id" : self._id,
             "variable_name" : self.name,
         }
         return State(
@@ -121,7 +128,8 @@ def llnode_delete(self,comments=""):
             comments=comments
         )
 
-class LinkedListNode:
+@serialize
+class LinkedListNode(ARgorithmStructure, ARgorithmHashable):
     """The LinkedListNode class is an implementation of a Linked list Node for
     which we store states. Unlike other data structure classes, in which we
     have to give a name to the instance, we dont have to provide name in the
@@ -146,14 +154,15 @@ class LinkedListNode:
     """
 
     def __init__(self,algo:StateSet,value=None,comments=""):
-        self.name = id(self)
+        self.name = str(id(self))
+        self._id = str(id(self))
         try:
             assert isinstance(algo,StateSet)
             self.algo = algo
         except AssertionError as e:
             raise ARgorithmError("algo should be of type StateSet") from e
 
-        self.state_generator = LinkedListNodeState(self.name)
+        self.state_generator = LinkedListNodeState(self.name, self._id)
 
         self._flag = False
         self.value = value
@@ -220,9 +229,11 @@ class LinkedListState:
     Attributes:
 
         name (str) : Name of the variable for whom we are generating states
+        _id (str) : id of the variable for whom we are generating states
     """
-    def __init__(self,name:str):
+    def __init__(self,name:str,_id:str):
         self.name = name
+        self._id = _id
 
     def ll_declare(self,head,comments=""):
         """Generates the `ll_declare` state when a new linkedlist is created.
@@ -236,6 +247,7 @@ def ll_declare(self,head,comments=""):
         """
         state_type = "ll_declare"
         state_def = {
+            "id" : self._id,
             "variable_name" : self.name,
             "head" : head.name if head else "none"
         }
@@ -245,7 +257,7 @@ def ll_declare(self,head,comments=""):
             comments=comments
         )
 
-    def ll_head(self,head,comments=""):
+    def ll_head(self,head,last_head=None,comments=""):
         """Generates the `ll_head` state when linkedlist head is changed.
 
         Args:
@@ -257,16 +269,20 @@ def ll_head(self,head,comments=""):
         """
         state_type = "ll_head"
         state_def = {
+            "id" : self._id,
             "variable_name" : self.name,
             "head" : head.name if head else "none"
         }
+        if not (last_head is None):
+            state_def["last_head"] = last_head
         return State(
             state_type=state_type,
             state_def=state_def,
             comments=comments
         )
 
-class LinkedList:
+@serialize
+class LinkedList(ARgorithmStructure, ARgorithmHashable):
     """The LinkedList class is used to just store the head of the linked list.
 
     This class is useful when programmer want to program his own List class using
@@ -292,12 +308,13 @@ def __init__(self,name:str,algo:StateSet,head=None,comments=""):
 
         assert isinstance(name,str) , ARgorithmError("Name should be of type string")
         self.name = name
+        self._id = str(id(self))
         try:
             assert isinstance(algo,StateSet)
             self.algo = algo
         except AssertionError as e:
             raise ARgorithmError("algo should be of type StateSet") from e
-        self.state_generator = LinkedListState(self.name)
+        self.state_generator = LinkedListState(self.name, self._id)
 
         self._flag = False
         if head:
@@ -315,11 +332,14 @@ def __setattr__(self,key,value):
         Raises:
             ARgorithmError: Raised if head pointer is not type None or LinkedListNode
         """
+        last_head = None
         if key == 'head' and value:
             assert isinstance(value,LinkedListNode) , ARgorithmError("next should be of type None or LinkedListNode")
+        if key == 'head' and self._flag:
+            last_head = self.head._id if self.head else "none"
         self.__dict__[key] = value
         if key == 'head' and self._flag:
-            state = self.state_generator.ll_head(self.head,"head pointer shifts")
+            state = self.state_generator.ll_head(self.head,last_head=last_head, comments="head pointer shifts")
             self.algo.add_state(state)
 
     def __str__(self):
diff --git a/ARgorithmToolkit/map.py b/ARgorithmToolkit/map.py
new file mode 100644
index 0000000..740f514
--- /dev/null
+++ b/ARgorithmToolkit/map.py
@@ -0,0 +1,462 @@
+"""The map module provides support for hash-map or dictionary data structure for the Toolkit.
+It maps key to a value provided.
+Provides O(1) average case and O(n) amortized worst case complexity for element lookup.
+The main class in this module is the Map class. The
+other classes act as support class to Map class. For this reason the Map
+class can directly be imported from the ARgorithmToolkit library without having
+to import from the map module :
+
+    >>> map = ARgorithmToolkit.Map(name='map',algo=algo)
+    >>> map = ARgorithmToolkit.map.Map(name='map',algo=algo)
+"""
+
+from ARgorithmToolkit.utils import ARgorithmHashable, State, StateSet, ARgorithmError, ARgorithmStructure
+from ARgorithmToolkit.encoders import serialize
+
+class MapState:
+    """This class is used to generate states for various actions performed on
+    the ``ARgorithmToolkit.map.Map`` object.
+
+    Attributes:
+
+        name (str) : Name of the object for which the states are generated
+        _id (str) : id of the object for which the states are generated
+    """
+    def __init__(self,name,_id):
+        self.name = name
+        self._id = _id
+
+    def map_declare(self, body, comments="") -> State:
+        """Generates the `map_declare` state when an instance of Map class
+        is created.
+
+        Args:
+            body: The contents of the map that are to be sent along with the state
+            comments (optional): The comments that are supposed to rendered with the state for descriptive purpose. Defaults to "".
+
+        Returns:
+            ARgorithmToolkit.utils.State: returns the ``map_declare`` state for the respective map mentioned
+        """
+        state_type = "map_declare"
+        state_def = {
+            "id": self._id,
+            "variable_name" : self.name,
+            "body" : body.copy()
+        }
+        return State(
+            state_type=state_type,
+            state_def=state_def,
+            comments=comments
+        )
+
+    def map_get(self,body,key,value,comments="") -> State:
+        """Generates the `map_get` state when a particular key is looked up.
+
+        Args:
+            body : The contents of the map that are to be sent along with the state
+            key : The key that has been accessed
+            value : The current value associated with key
+            comments (optional): The comments that are supposed to rendered with the state for descriptive purpose. Defaults to "".
+
+        Returns:
+            ARgorithmToolkit.utils.State: returns the ``map_get`` state for the respective map mentioned
+        """
+        state_type = "map_get"
+        state_def = {
+            "id" : self._id,
+            "variable_name" : self.name,
+            "body" : body.copy(),
+            "key" : key,
+            "value" : value
+        }
+        return State(
+            state_type=state_type,
+            state_def=state_def,
+            comments=comments
+        )
+
+    def map_set(self,body,key,value,last_value=None,comments="") -> State:
+        """Generates the `map_set` state when a particular key is set for a new value.
+
+        Args:
+            body : The contents of the map that are to be sent along with the state
+            key : The key that has been accessed
+            value : The current value being associated with key
+            last_value (optional): the last value that the key was associated to.
+            comments (optional): The comments that are supposed to rendered with the state for descriptive purpose. Defaults to "".
+
+        Returns:
+            ARgorithmToolkit.utils.State: returns the ``map_set`` state for the respective map mentioned
+        """
+        state_type = "map_set"
+        state_def = {
+            "id" : self._id,
+            "variable_name" : self.name,
+            "body" : body.copy(),
+            "key" : key,
+            "value" : value,
+            "last_value" : last_value
+        }
+        return State(
+            state_type=state_type,
+            state_def=state_def,
+            comments=comments
+        )
+
+
+    def map_remove(self,body,key,value,comments="") -> State:
+        """Generates the `map_remove` state when a particular key is deleted.
+
+        Args:
+            body : The contents of the map that are to be sent along with the state
+            key : The key that has been deleted
+            value : The value associated with key
+            comments (optional): The comments that are supposed to rendered with the state for descriptive purpose. Defaults to "".
+
+        Returns:
+            ARgorithmToolkit.utils.State: returns the ``map_remove`` state for the respective map mentioned
+        """
+        state_type = "map_remove"
+        state_def = {
+            "id" : self._id,
+            "variable_name" : self.name,
+            "body" : body.copy(),
+            "key" : key,
+            "value" : value,
+        }
+        return State(
+            state_type=state_type,
+            state_def=state_def,
+            comments=comments
+        )
+
+class MapIterator:
+    """This class is a generator that is returned each time an map has to be
+    iterated.
+
+    Yields:
+        Tuple(key,value) of Map
+
+    Raises:
+        AssertionError: If not declared with an instance of ARgorithmToolkit.map.Map
+    """
+    def __init__(self,_map):
+        assert isinstance(_map,Map)
+        self.map = _map
+        self.size = len(_map)
+        self.index = 0
+        self.keys = list(self.map.keys())
+        self.values = list(self.map.values())
+
+    def __next__(self) -> tuple:
+        if self.index == self.size:
+            raise StopIteration
+        k = self.keys[self.index]
+        v = self.values[self.index]
+        self.index += 1
+        return k,v
+
+@serialize
+class Map(ARgorithmStructure):
+    """The Map class used to emulate hash-maps/dictionaries that can be
+    rendered in the ARgorithm Application as series of key/value pairs.
+
+    Attributes:
+        name (str): name given to the rendered block in augmented reality. Essential. Should not be altered after initialisation
+        algo (ARgorithmToolkit.utils.StateSet): The stateset that will store the states generated by the instance of Map Class
+        comments (str,optional): Description of instance of map and its applications that will be rendered during the ``map_declare`` state.
+
+    Raises:
+        ARgorithmError: raised if name is not given or Stateset if not provided
+
+    Examples:
+        This is an example of map being declared
+
+        >>> algo = ARgorithmToolkit.StateSet()
+        >>> map = ARgorithmToolkit.Map(name='map',algo=algo)
+        >>> map
+        Map({})
+
+        The map generated supports all the functionality of regular dictionary
+
+        >>> len(map)
+        0
+        >>> map["hello"] = 2
+        >>> map["hello"]
+        2
+        >>> map[3] = "s"
+        >>> map
+        Map({"hello":2, 3:"s"})
+        >>> for key,value in map:
+        ...     print(key, value)
+        hello 2
+        3 s
+        >>> del map[3]
+        >>> map
+        Map({"hello":2})
+    """
+
+    def __init__(self, name:str, algo:StateSet, comments:str = ""):
+        try:
+            assert isinstance(name, str)
+            self.state_generator = MapState(name, str(id(self)))
+        except Exception as ex:
+            raise ARgorithmError('Give valid name to data structure') from ex
+        try:
+            assert isinstance(algo, StateSet)
+            self.algo = algo
+        except Exception as ex:
+            raise ARgorithmError("Map structure needs a reference of template to store states") from ex
+
+        self.body = {}
+        self.__working_dict = {}
+        state = self.state_generator.map_declare(self.body,comments)
+        self.algo.add_state(state)
+
+
+    def __len__(self) -> int:
+        """returns size of Map when processed by len() function.
+
+        Returns:
+            int: size of the map
+
+        Example:
+            >>> map
+            Map({"abc":2, "efg":3})
+            >>> len(map)
+            2
+        """
+        return len(self.__working_dict)
+
+    def __getitem__(self, key) -> any:
+        """returns the value associated with 'key' in the Map
+        Args:
+            key (ARgorithmStructure or (int, str, float, bool)): key to lookup in dict
+            comments (str, optional): Comments for descriptive purpose. Defaults to "".
+
+        Returns:
+            obj: value associated with the key provided
+
+        Example:
+            >>> map
+            Map({"abc":2, "efg":3})
+            >>> map["abc"]
+            2
+        """
+        try:
+            _value = self.__working_dict[key]
+            value = None
+            if isinstance(key, ARgorithmHashable):
+                value = self.body[key.to_json()]
+            else:
+                value = self.body[key]
+            state = self.state_generator.map_get(body=self.body, key=key, value=value, comments="")
+            self.algo.add_state(state)
+            return _value
+        except Exception as e:
+            raise ARgorithmError(f"Invalid Key Error : {str(e)}") from e
+
+
+    def get(self, key, default=None, comments="") -> any:
+        """returns the value associated with 'key' in the Map without raising key error
+        Args:
+            key (ARgorithmStructure or (int, str, float, bool)) : key to lookup in dict
+            default : return a default value for non-existent key instead of raising an error
+            comments (str, optional): Comments for descriptive purpose. Defaults to "".
+
+        Returns:
+            obj: value associated with the key provided
+
+        Example:
+            >>> map
+            Map({"abc":2, "efg":3})
+            >>> map.get("xyz", -1) #get usage
+            -1
+            >>> map.get("xyz") is None
+            True
+        """
+        try:
+            _value = self.__working_dict[key]
+            state = self.state_generator.map_get(body=self.body, key=key, value=_value, comments=comments)
+            self.algo.add_state(state)
+            return _value
+        except KeyError:
+            state = self.state_generator.map_get(body=self.body, key=key, value=default if default else "none", comments=f"key not found. value efaulted to {default}")
+            self.algo.add_state(state)
+            return default
+
+    def set(self, key, value, comments=""):
+        """sets a value mapped to a given key in the Map
+        Args:
+            key (ARgorithmStructure or (int, str, float, bool)) : key to set in the dict
+            value (ARgorithmStructure of (int, str, float, bool)) : value to set in the dict
+            comments (str, optional): Comments for descriptive purpose. Defaults to "".
+
+        Example:
+            >>> map
+            Map({"abc":2, "efg":3})
+            >>> map.set("xyz, 5) #__setitem__ usage
+            >>> map.get("xyz", -1)
+            5
+            >>> map["xyz"]
+            5
+        """
+        assert isinstance(key,(ARgorithmHashable, int, str, float, bool)), f"Invalid key : key cannot be any type other than (ARgorithmHashable, int, str, float, bool), {type(key).__name__} is not hashable."
+        assert isinstance(value,(ARgorithmStructure, int, str, float, bool)), "Invalid value : value cannot be set to any type other than (ARgorithmStructure, int, str, float, bool)"
+        last_value = self.body.get(key, "none")
+        self.__working_dict[key] = value
+        if isinstance(key, (str, int, float, bool)) and isinstance(value, (str, int, float, bool)):
+            self.body[key] = value
+        elif isinstance(key, (str, int, float, bool)):
+            self.body[key] = value.to_json()
+        elif isinstance(value, (str, int, float, bool)):
+            self.body[key.to_json()] = value
+        else:
+            self.body[key.to_json()] = value.to_json()
+
+        state = self.state_generator.map_set(body=self.body, key=key, value=value, last_value=last_value, comments=comments)
+        self.algo.add_state(state)
+
+
+    def __setitem__(self, key, value, comments=""):
+        """sets a value mapped to a given key in the Map
+        Args:
+            key (ARgorithmStructure or (int, str, float, bool)) : key to set in the dict
+            value (ARgorithmStructure of (int, str, float, bool)) : value to set in the dict
+            comments (str, optional): Comments for descriptive purpose. Defaults to "".
+
+        Example:
+            >>> map
+            Map({"abc":2, "efg":3})
+            >>> map["xyz"] = 5 #__setitem__ usage
+            >>> map.get("xyz", -1)
+            5
+            >>> map["xyz"]
+            5
+        """
+        assert isinstance(key,(ARgorithmHashable, int, str, float, bool)), f"Invalid key : key cannot be any type other than (ARgorithmHashable, int, str, float, bool), {type(key).__name__} is not hashable."
+        assert isinstance(value,(ARgorithmStructure, int, str, float, bool)), "Invalid value : value cannot be set to any type other than (ARgorithmStructure, int, str, float, bool)"
+        last_value = self.body.get(key, "none")
+        self.__working_dict[key] = value
+        if isinstance(key, (str, int, float, bool)) and isinstance(value, (str, int, float, bool)):
+            self.body[key] = value
+        elif isinstance(key, (str, int, float, bool)):
+            self.body[key] = value.to_json()
+        elif isinstance(value, (str, int, float, bool)):
+            self.body[key.to_json()] = value
+        else:
+            self.body[key.to_json()] = value.to_json()
+
+        state = self.state_generator.map_set(body=self.body, key=key, value=value, last_value=last_value, comments="")
+        self.algo.add_state(state)
+
+    def __iter__(self):
+        """Generates a iterator object to iterate the map key/value pairs
+
+        Returns:
+            MapIterator: Iterator object
+
+        Example:
+            >>> map
+            Map({"abc":3, "efg":4})
+            >>> [x for x in map]
+            [("abc",3),("efg",4)]
+        """
+        return MapIterator(self)
+
+    def __delitem__(self, key):
+        """deletes the entry associated with 'key' in the Map
+        Args:
+            key (ARgorithmHashable or (int, str, float, bool)) : key to lookup in dict
+            comments (str, optional): Comments for descriptive purpose. Defaults to "".
+
+        Example:
+            >>> map
+            Map({"abc":2, "efg":3})
+            >>> del map["abc"] # __delitem__ usage
+            >>> map
+            Map({"efg":3})
+        """
+        try:
+            value = None
+            if isinstance(key, ARgorithmHashable):
+                value = self.body[key.to_json()]
+                del self.body[key.to_json()]
+            else:
+                value = self.body[key]
+                del self.body[key]
+
+            del self.__working_dict[key]
+            state = self.state_generator.map_remove(self.body, key, value, "")
+            self.algo.add_state(state)
+
+        except Exception as e:
+            raise ARgorithmError(f"Invalid Key Error : {str(e)}") from e
+
+    def remove(self, key, comments=""):
+        """deletes the entry associated with 'key' in the Map without raising an error
+        Args:
+            key (ARgorithmHashable or (int, str, float, bool)) : key to lookup in dict
+            comments (str, optional): Comments for descriptive purpose. Defaults to "".
+
+        Example:
+            >>> map
+            Map({"abc":2, "efg":3})
+            >>> map.remove("abc")
+            >>> map
+            Map({"efg":3})
+            >>> map.remove("abc")
+            >>> map
+            Map({"efg":3})
+        """
+        try:
+            value = None
+            if isinstance(key, ARgorithmHashable):
+                value = self.body[key.to_json()]
+                del self.body[key.to_json()]
+            else:
+                value = self.body[key]
+                del self.body[key]
+
+            del self.__working_dict[key]
+            state = self.state_generator.map_remove(self.body, key, value, comments)
+            self.algo.add_state(state)
+
+        except KeyError:
+            state = self.state_generator.map_remove(self.body, key, "none", "key not found, nothing removed.")
+            self.algo.add_state(state)
+            return
+
+    def __repr__(self) -> str:
+        """Return representation for shell outputs.
+
+        Returns:
+            str: shell representation for Map
+        """
+        return f"Map({self.__working_dict.__repr__()})"
+
+    def __str__(self) -> str:
+        """Return string conversion for map
+
+        Returns:
+            str: string conversion for Map
+        """
+        return f"Map({self.__working_dict.__str__()})"
+
+    def keys(self):
+        """Returns a list of key entries in the map
+
+        Returns:
+            list: list of keys
+        """
+
+        return self.__working_dict.keys()
+
+    def values(self):
+        """Returns a list of values in the map
+
+        Returns:
+            list: list of values
+        """
+
+        return self.__working_dict.values()
diff --git a/ARgorithmToolkit/parser.py b/ARgorithmToolkit/parser.py
new file mode 100644
index 0000000..6d62c1e
--- /dev/null
+++ b/ARgorithmToolkit/parser.py
@@ -0,0 +1,434 @@
+# pylint: skip-file
+"""Parser module deals with parsing .config.json files
+"""
+import os
+import json
+import re
+import math
+import inspect
+import typer
+from jsonschema import Draft7Validator
+from jsonschema.exceptions import ValidationError
+
+import ARgorithmToolkit
+
+with open(os.path.join(ARgorithmToolkit.__path__[0],'data/config.schema.json')) as schema:
+    CONFIG_SCHEMA = json.load(schema)
+
+config_cli_heading ="""
+    +-----------------------------+
+    |                             |
+    |  ARGORITHM CONFIG GENERATOR |
+    |                             |
+    +-----------------------------+
+"""
+
+def multiline():
+    """takes multiline input
+    """
+    buffer = ''
+    while True:
+        try:
+            line = input()
+        except EOFError:
+            break
+        if not line:
+            break
+        buffer += line+"\n"
+    return buffer[:-1]
+
+def master_heading():
+    """Renders the ARgorithm config generator heading
+    """
+    text = typer.style(config_cli_heading,fg=typer.colors.BLUE,bold=True)
+    typer.echo(text)
+
+def heading(title,message):
+    """Create a heading text
+
+    Args:
+        title (str): The title of the heading
+        message (str): The message that
+    """
+    # typer.clear()
+    text = typer.style(title.upper(),fg=typer.colors.BLUE,bold=True)
+    typer.echo('-'*(len(text)+2))
+    typer.echo(text)
+    typer.echo('-'*(len(text)+2))
+    typer.echo(message+"\n")
+    return typer
+
+def input_prompt(message,default=None,type=str,show_default=True):
+    """Uses typer to create a single input field in CLI
+
+    Args:
+        message (str): The input field text
+        type (type, optional): The type of input
+        default (type, optional): The default value if user does not enter any value
+        show_default (bool, optional): By default, True. If True shows the default value to user
+
+    Returns:
+        ip : The data entered by user
+    """
+    text = typer.style(message,fg=typer.colors.BLUE)
+    if default:
+        ip = typer.prompt(text,default=default,type=type,show_default=show_default)
+    else:
+        ip = typer.prompt(text,type=type)
+    return ip
+
+def confirm_prompt(message):
+    """Uses typer to create a confirmation prompt
+
+    Args:
+        message (str): The text for confirmation
+
+    Returns:
+        flag: boolean value as entered by user
+    """
+    text = typer.style(message,fg=typer.colors.BLUE)
+    flag = typer.confirm(text)
+    return flag
+
+def multiline_input_prompt(message):
+    """Uses typer and ARgorithmToolkit.parser.multiline to create a multiline input prompt
+
+    Args:
+        message (str): The text for prompt
+
+    Returns:
+        ip: data entered by user
+    """
+    text = typer.style(message + ':',fg=typer.colors.BLUE)
+    helptext = typer.style("Press ENTER on empty line to leave multiline input",fg=typer.colors.CYAN)
+    typer.echo(text)
+    typer.echo(helptext)
+    ip = multiline()
+    return ip
+
+def info(message,data):
+    """Display information using typer
+
+    Args:
+        message (str): Description of the information
+        data : The data to be displayed
+    """
+    message = typer.style(message,fg=typer.colors.BLUE)
+    data = typer.style(str(data),fg=typer.colors.GREEN)
+    typer.echo(message+": "+data)
+
+def warning(message):
+    """Generate warning message using typer
+
+    Args:
+        message (str): warning text
+    """
+    text = typer.style("⚠  " + message , fg=typer.colors.YELLOW)
+    typer.echo(text)
+
+def find_parameters(filename,function):
+    """Finds the keyword arguments accessed in the file
+
+    find_parameters parses the code line by line and check which all keywords
+    were accessed in the function code within the code file
+
+    Args:
+        filename (str): filename of the codefile
+        function (str): function name where we need to check the kwargs
+
+    Returns:
+        params: list of keywords which need to be defined in config file
+    """
+    function_regex = re.compile(f"^def.([A-Za-z0-9]+).?\(\*\*kwargs\)")
+    kwarg_regex = r"kwargs\[[\'\"]([A-Za-z0-9]+)[\'\"]\]"
+    with open(filename,'r') as codefile:
+        parameters = set()
+        flag = False
+        for line in codefile.readlines():
+            search = re.search(function_regex,line)
+            if search:
+                func = list(search.groups())[0]
+                flag = func == function
+            if flag:
+                search = re.search(kwarg_regex,line)
+                if search:
+                    params = list(search.groups())
+                    for p in params:
+                        parameters.add(p)
+        return list(parameters)
+
+def input_data(parameters):
+    """Generates a input form based on the parameters in config
+
+    Args:
+        parameters (dict): The config parameters which will be used to generate the input fields
+
+    Returns:
+        example: The values for each param (key in parameters)
+    """
+    example = {}
+    types = {
+        "INT" : int,
+        "FLOAT" : float,
+        "STRING" : str,
+    }
+    heading("Enter input for ARgorithm","Based on argorithm parameters, input will be taken")
+    for key in parameters:
+        param = parameters[key]
+        # typer.clear()
+        info("\ninput keyword",key)
+        info("Description",param['description'])
+
+        def numeric_input(param,input_type):
+            retry = True
+            while retry:
+                retry = False
+                value = input_prompt("Enter integer value",type=input_type)
+                if "start" in param:
+                    if value <= param["start"]:
+                        warning(f"Please enter value larger than {param['start']}")
+                        retry = True
+                if "end" in param:
+                    if value >= param["end"]:
+                        warning(f"Please enter value less than {param['end']}")
+                        retry = True
+            return input_type(value)
+
+        def check_size(value,param,example):
+            if "size" in param:
+                if isinstance(param["size"],str):
+                    assert isinstance(example[param["size"]],int)
+                    if len(value) != example[param["size"]]:
+                        warning(f"length of string should be {example[param['size']]}")
+                        return True
+                else:
+                    if len(value) != param["size"]:
+                        warning(f"length of string should be {param['size']}")
+                        return True
+            return False
+
+        if param["type"] == "INT":
+            value = numeric_input(param,int)
+
+        elif param["type"] == "FLOAT":
+            value = numeric_input(param,float)
+
+        elif param["type"] == "STRING":
+            retry = True
+            while retry:
+                retry = False
+                value = input_prompt("Enter string value" , type=str)
+                retry = check_size(value,param,example)
+
+        elif param["type"] == "ARRAY":
+            retry = True
+            while retry:
+                retry = False
+                value = input_prompt("Enter space separated series" , type=str).split(' ')
+                try:
+                    value = [types[param['item-type']](x) for x in value]
+                except:
+                    warning(f"elements must be of type {types[param['item-type']]}")
+                    retry = True
+                retry = check_size(value,param,example)
+
+        elif param["type"] == "MATRIX":
+            retry = True
+            while retry:
+                retry = False
+                if isinstance(param['row'],str):
+                    row_count = example[param['row']]
+                else:
+                    row_count = param['row']
+                if isinstance(param['col'],str):
+                    col_count = example[param['col']]
+                else:
+                    col_count = param['col']
+                typer.echo("Enter matrix input, elements in each row must be space separated")
+                info(f"no. of rows", row_count)
+                info(f"no. of elements per row",col_count)
+                value = []
+                for _ in range(row_count):
+                    row_value = input_prompt("",type=str).split(' ')
+                    if len(row_value) != col_count:
+                        warning(f"row must have {col_count} space separated values")
+                        retry = True
+                    try:
+                        row_value = [types[param['item-type']](x) for x in row_value]
+                    except:
+                        warning(f"elements must be of type {types[param['item-type']]}")
+                        retry = True
+                    if retry:
+                        break
+                    value.append(row_value)
+        example[key] = value
+    return example
+
+class ARgorithmConfig:
+    """Validates and stores argorithm config
+    """
+    def __init__(self,filepath):
+        self.validator = Draft7Validator(CONFIG_SCHEMA)
+        directory = os.getcwd()
+        if os.path.isfile( os.path.join(directory , f"{filepath}") ):
+            with open(os.path.join(directory , f"{filepath}") , 'r') as configfile:
+                data = json.load(configfile)
+                try:
+                    self.validator.validate(data)
+                except ValidationError as ve:
+                    raise ve
+                self.config = data
+        else:
+            confirm = typer.confirm("Start CLI config generator? ")
+            if confirm:
+                self.create(filepath)
+            else:
+                raise FileNotFoundError("No config file")
+
+    def create(self,filepath):
+        """implements the CLI config generator to run create config files using CLI
+        """
+        master_heading()
+
+        config = {}
+
+        info("ARgorithmID", filepath.split(".")[0])
+        config["argorithmID"] = filepath.split(".")[0]
+        config["file"] = config["argorithmID"]+".py"
+
+        function_regex = re.compile("def.([A-Za-z]+).?\(\*\*kwargs\)")
+        with open(config["file"],"r") as codefile:
+            text = codefile.read()
+        func_list = list(re.search(function_regex,text).groups())
+        if len(func_list) == 0:
+            raise KeyError("No valid function in ARgorithm code")
+        info("Codefile found",config['file'])
+        function = input_prompt("which function should be called",default=func_list[0])
+        while function not in func_list:
+            warning("function not found in code")
+            function = input_prompt("enter valid function name",default=func_list[0])
+        config["function"] = function
+
+        config["description"] = multiline_input_prompt('Enter ARgorithm Description')
+        config["parameters"] = {}
+
+        def define_parameter(config,parameter_name):
+            """Nested function that asks use information regarding parameter
+
+            Args:
+                config (dict): The config object where the parameter data has to be updated
+                parameter_name (str): The parameter whose metadata is being collected
+
+            Returns:
+                config: Returns updated config object
+            """
+            parameter_types = ["INT","FLOAT","STRING","ARRAY","MATRIX"]
+            parameter_type = input_prompt("Enter parameter type")
+            while parameter_type not in parameter_types:
+                warning("Invalid parameter type. Accepted values: INT FLOAT ARRAY MATRIX STRING")
+                parameter_type = input_prompt("Enter parameter type")
+            config["parameters"][parameter_name]["type"] = parameter_type
+
+            def range_input(config,parameter_name):
+                """Update config with the range for `INT` and `FLOAT` parameters
+
+                Args:
+                    config (dict): The config object where the parameter data has to be updated
+                    parameter_name (str): The parameter whose metadata is being collected
+                """
+                start = input_prompt("Enter lower limit",type=int,default=-math.inf,show_default=False)
+                if start != -math.inf:
+                    config["parameters"][parameter_name]["start"] = start
+                end = input_prompt("Enter upper limit",type=int,default=math.inf,show_default=False)
+                if end != math.inf:
+                    config["parameters"][parameter_name]["end"] = end
+
+            def size_ref(data_field):
+                """Inputs size constraint for `STRING`,`ARRAY` and `MATRIX` parameters
+
+                Args:
+                    data_field (str): What is the size constraint being used as
+
+                Returns:
+                    size: Returns size constraint
+                """
+                size = input_prompt(f"Enter integer {data_field} or name of pre-existing INT type parameter")
+                try:
+                    size = int(size)
+                except ValueError:
+                    assert size in config["parameters"]
+                return size
+
+            if parameter_type == "INT":
+                range_confirm = confirm_prompt(f"Do you want to add range constraints to {parameter_name}")
+                if range_confirm:
+                    range_input(config,parameter_name)
+
+            elif parameter_type == "FLOAT":
+                range_confirm = confirm_prompt(f"Do you want to add range constraints to {parameter_name}")
+                if range_confirm:
+                    range_input(config,parameter_name)
+
+            elif parameter_type == "STRING":
+                range_confirm = confirm_prompt(f"Do you want to set a size constraint to {parameter_name}")
+                if range_confirm:
+                    config["parameters"][parameter_name]["size"] = size_ref("size")
+
+            elif parameter_type == "ARRAY":
+                item_types = ["INT","FLOAT","STRING"]
+                item_type = input_prompt("Enter type of array element")
+                while item_type not in item_types:
+                    warning("Invalid element type. Accepted values: INT FLOAT STRING")
+                    item_type = input_prompt("Enter item type")
+                config["parameters"][parameter_name]["item-type"] = item_type
+                range_confirm = confirm_prompt(f"Do you want to set a size constraint to {parameter_name}")
+                if range_confirm:
+                    config["parameters"][parameter_name]["size"] = size_ref("size")
+
+            elif parameter_type == "MATRIX":
+                item_types = ["INT","FLOAT","STRING"]
+                item_type = input_prompt("Enter type of array element")
+                while item_type not in item_types:
+                    warning("Invalid element type. Accepted values: INT FLOAT STRING")
+                    item_type = input_prompt("Enter item type")
+                config["parameters"][parameter_name]["item-type"] = item_type
+                config["parameters"][parameter_name]["row"] = size_ref('row size')
+                config["parameters"][parameter_name]["col"] = size_ref('col_size')
+
+            parameter_description = multiline_input_prompt("Enter parameter description")
+            config["parameters"][parameter_name]["description"] = parameter_description
+
+            return config
+
+        typer.echo("Setting up parameters for your argorithm")
+        typer.echo("input keywords are used to map the input passed to your function as kwargs")
+        print()
+        existing_parameters = find_parameters(config['file'],config['function'])
+        if len(existing_parameters) > 0:
+            text = typer.style('The following input keywords were found in code')
+            typer.echo(text)
+        for param in existing_parameters:
+            typer.echo(typer.style("- "+param,fg=typer.colors.GREEN))
+            config["parameters"][param] = {}
+
+        for param in existing_parameters:
+            info("input keyword",param)
+            config = define_parameter(config,param)
+
+        confirm = confirm_prompt("Do you want to another input keyword")
+        while(confirm):
+            typer.echo("add details for parameter")
+            parameter_name = input_prompt("Enter parameter name")
+            name_regex = r"^[A-Za-z].*$"
+            while re.match(name_regex,parameter_name) is None:
+                warning("Invalid name")
+                parameter_name = input_prompt("re-enter parameter name")
+            config["parameters"][parameter_name] = {}
+            config = define_parameter(config,parameter_name)
+
+            confirm = confirm_prompt("Do you want to add parameter?")
+        example = input_data(config["parameters"])
+        config["example"] = example
+        directory = os.getcwd()
+        with open(os.path.join(directory , f"{filepath}") , 'w') as configfile:
+            json.dump(config,configfile)
diff --git a/ARgorithmToolkit/priorityqueue.py b/ARgorithmToolkit/priorityqueue.py
index 339a7fb..8257961 100644
--- a/ARgorithmToolkit/priorityqueue.py
+++ b/ARgorithmToolkit/priorityqueue.py
@@ -9,7 +9,8 @@
     >>> pq = ARgorithmToolkit.PriorityQueue(name="pq",algo=algo)
 """
 import heapq
-from ARgorithmToolkit.utils import State, StateSet, ARgorithmError
+from ARgorithmToolkit.utils import State, StateSet, ARgorithmError, ARgorithmStructure
+from ARgorithmToolkit.encoders import serialize
 
 class PriorityQueueState():
     """This class is used to generate states for various actions performed on
@@ -18,9 +19,11 @@ class PriorityQueueState():
     Attributes:
 
         name (str) : Name of the variable for whom we are generating states
+        _id (str) : id of the variable for whom we are generating states
     """
-    def __init__(self,name):
+    def __init__(self,name,_id):
         self.name = name
+        self._id = _id
 
     def priorityqueue_declare(self,comments=""):
         """Generates the `priorityqueue_declare` state when an instance of
@@ -35,6 +38,7 @@ def priorityqueue_declare(self,comments=""):
         """
         state_type = "priorityqueue_declare"
         state_def = {
+            "id" : self._id,
             "variable_name" : self.name,
             "body" : []
         }
@@ -58,6 +62,7 @@ def priorityqueue_offer(self,body,element,comments=""):
         """
         state_type = "priorityqueue_offer"
         state_def = {
+            "id" : self._id,
             "variable_name" : self.name,
             "body" : list(body),
             "element" : element
@@ -81,6 +86,7 @@ def priorityqueue_poll(self,body,comments=""):
         """
         state_type = "priorityqueue_poll"
         state_def = {
+            "id" : self._id,
             "variable_name" : self.name,
             "body" : list(body),
         }
@@ -103,6 +109,7 @@ def priorityqueue_peek(self,body,comments=""):
         """
         state_type = "priorityqueue_peek"
         state_def = {
+            "id" : self._id,
             "variable_name" : self.name,
             "body" : list(body),
         }
@@ -112,7 +119,8 @@ def priorityqueue_peek(self,body,comments=""):
             comments=comments
         )
 
-class PriorityQueue:
+@serialize
+class PriorityQueue(ARgorithmStructure):
     """The PriorityQueue class offes a priority queue container that stores
     states in its stateset which later are used to make dynamic Augmented
     reality visualizations.
@@ -133,7 +141,8 @@ class PriorityQueue:
     def __init__(self, name:str, algo:StateSet, comments:str = ""):
         try:
             assert isinstance(name,str)
-            self.state_generator = PriorityQueueState(name)
+            self._id = str(id(self))
+            self.state_generator = PriorityQueueState(name, self._id)
         except AssertionError as e:
             raise ARgorithmError('Give valid name to data structure') from e
         try:
diff --git a/ARgorithmToolkit/queue.py b/ARgorithmToolkit/queue.py
index 099a4cd..01458c8 100644
--- a/ARgorithmToolkit/queue.py
+++ b/ARgorithmToolkit/queue.py
@@ -7,8 +7,9 @@
     >>> q = ARgorithmToolkit.Queue(name="q",algo=algo)
 """
 
+from ARgorithmToolkit.utils import State, StateSet, ARgorithmError, ARgorithmStructure
+from ARgorithmToolkit.encoders import serialize
 
-from ARgorithmToolkit.utils import State, StateSet, ARgorithmError
 class QueueState():
     """This class is used to generate states for various actions performed on
     the ``ARgorithmToolkit.queue.Queue`` object.
@@ -16,9 +17,11 @@ class QueueState():
     Attributes:
 
         name (str) : Name of the variable for whom we are generating states
+        _id (str) : id of the variable for whom we are generating states
     """
-    def __init__(self,name):
+    def __init__(self,name,_id):
         self.name = name
+        self._id = _id
 
     def queue_declare(self,comments=""):
         """Generates the `queue_declare` state when an instance of queue is
@@ -32,6 +35,7 @@ def queue_declare(self,comments=""):
         """
         state_type = "queue_declare"
         state_def = {
+            "id" : self._id,
             "variable_name" : self.name,
             "body" : []
         }
@@ -54,6 +58,7 @@ def queue_push(self,body,element,comments=""):
         """
         state_type = "queue_push"
         state_def = {
+            "id" : self._id,
             "variable_name" : self.name,
             "body" : list(body),
             "element" : element
@@ -77,6 +82,7 @@ def queue_pop(self,body,comments=""):
         """
         state_type = "queue_pop"
         state_def = {
+            "id" : self._id,
             "variable_name" : self.name,
             "body" : list(body),
         }
@@ -98,6 +104,7 @@ def queue_front(self,body,comments=""):
         """
         state_type = "queue_front"
         state_def = {
+            "id" : self._id,
             "variable_name" : self.name,
             "body" : list(body),
         }
@@ -119,6 +126,7 @@ def queue_back(self,body,comments=""):
         """
         state_type = "queue_back"
         state_def = {
+            "id" : self._id,
             "variable_name" : self.name,
             "body" : list(body),
         }
@@ -128,7 +136,8 @@ def queue_back(self,body,comments=""):
             comments=comments
         )
 
-class Queue:
+@serialize
+class Queue(ARgorithmStructure):
     """The Queue class is a container interface for the queue, a linear
     container implementation of FIFO.
 
@@ -148,7 +157,8 @@ class Queue:
     def __init__(self, name:str, algo:StateSet, comments:str = ""):
         try:
             assert isinstance(name,str)
-            self.state_generator = QueueState(name)
+            self._id = str(id(self))
+            self.state_generator = QueueState(name, self._id)
         except AssertionError as e:
             raise ARgorithmError('Give valid name to data structure') from e
         try:
diff --git a/ARgorithmToolkit/security.py b/ARgorithmToolkit/security.py
new file mode 100644
index 0000000..8422235
--- /dev/null
+++ b/ARgorithmToolkit/security.py
@@ -0,0 +1,63 @@
+"""Security module contains functions to secure code files and prevent harmful code injection at server side
+"""
+import re
+import importlib
+from pyflakes import checker
+from ARgorithmToolkit import ARgorithmError,StateSet
+
+FORBIDDEN = [
+    'STORAGE_FOLDER','config',
+    'LRUCache','logger','PerformanceMonitor',
+    'eval'
+]
+
+def injection_check(filename:str):
+    """Checks whether given code file does not contain harmful code to server operation
+
+    Args:
+        filename (str): the code file to check
+
+    Raises:
+        ARgorithmError: Raised if possible harmful code injection
+    """
+    count = 0
+    with open(filename,'r') as f:
+        lines = f.readlines()
+        for line in lines:
+            if "import ARgorithmToolkit" in line or "from ARgorithmToolkit" in line:
+                count +=1
+        if count == 0:
+            raise ARgorithmError("ARgorithmToolkit not imported")
+
+        for line in lines:
+            if line.startswith("from"):
+                if not re.search(r"^from\s+ARgorithmToolkit", line):
+                    raise ARgorithmError("invalid module imported")
+
+        for line in lines:
+            if line.startswith("import"):
+                if not re.search(r"^import\s+ARgorithmToolkit", line):
+                    raise ARgorithmError("invalid module imported")
+
+        text = '\n'.join(lines)
+        file_tokens = checker.make_tokens(text)
+        tokens = [token[1] for token in file_tokens if token[0] == 1]
+        not_allowed = list(set(tokens) & set(FORBIDDEN))
+        if len(not_allowed) > 0:
+            raise ARgorithmError('possible code injection')
+
+def execution_check(filename:str,config:dict):
+    """Executes the file on kwargs provided by programmer in the config file's `example` key
+
+    Args:
+        filename (str): The file with the ARgorithm code to be checked
+        config (dict): The config file for ARgorithm
+    """
+    module_name = filename.split('/')[-1][:-3]
+    spec = importlib.util.spec_from_file_location(module_name,filename)
+    module = importlib.util.module_from_spec(spec)
+    spec.loader.exec_module(module)
+    func = getattr(module , config["function"])
+    parameters = config['example']
+    output = func(**parameters)
+    assert isinstance(output,StateSet)
diff --git a/ARgorithmToolkit/set.py b/ARgorithmToolkit/set.py
new file mode 100644
index 0000000..6a21de4
--- /dev/null
+++ b/ARgorithmToolkit/set.py
@@ -0,0 +1,375 @@
+"""The set module provides support for set data structure for the Toolkit.
+It stores keys and avoid duplication.
+Provides O(1) average case and O(n) amortized worst case complexity for element lookup.
+The main class in this module is the Set class. The
+other classes act as support class to Set class. For this reason the Set
+class can directly be imported from the ARgorithmToolkit library without having
+to import from the set module :
+
+    >>> set1 = ARgorithmToolkit.Set(name='set1',algo=algo,data=data)
+    >>> set1 = ARgorithmToolkit.set.Set(name='set1',algo=algo,data=data)
+"""
+
+from numpy.lib.function_base import iterable
+from numpy import generic
+from ARgorithmToolkit.utils import ARgorithmHashable, State, StateSet, ARgorithmError, ARgorithmStructure
+from ARgorithmToolkit.encoders import serialize
+
+class SetState:
+    """This class is used to generate states for various actions performed on
+    the ``ARgorithmToolkit.set.Set`` object.
+
+    Attributes:
+
+        name (str) : Name of the object for which the states are generated
+        _id (str) : id of the object for which the states are generated
+    """
+    def __init__(self,name,_id):
+        self.name = name
+        self._id = _id
+
+    def set_declare(self, body, comments="") -> State:
+        """Generates the `set_declare` state when an instance of Set class
+        is created.
+
+        Args:
+            body: The contents of the set that are to be sent along with the state
+            comments (optional): The comments that are supposed to rendered with the state for descriptive purpose. Defaults to "".
+
+        Returns:
+            ARgorithmToolkit.utils.State: returns the ``set_declare`` state for the respective set mentioned
+        """
+        state_type = "set_declare"
+        state_def = {
+            "id": self._id,
+            "variable_name" : self.name,
+            "body" : body.copy()
+        }
+        return State(
+            state_type=state_type,
+            state_def=state_def,
+            comments=comments
+        )
+
+    def set_add(self, body, key, comments="") -> State:
+        """Generates the `set_add` state when a particular key is add.
+
+        Args:
+            body : The contents of the set that are to be sent along with the state
+            key : The key that has been added
+            comments (optional): The comments that are supposed to rendered with the state for descriptive purpose. Defaults to "".
+
+        Returns:
+            ARgorithmToolkit.utils.State: returns the ``set_add`` state for the respective set mentioned
+        """
+        state_type = "set_add"
+        state_def = {
+            "id": self._id,
+            "variable_name" : self.name,
+            "key" : key,
+            "body" : body.copy()
+        }
+        return State(
+            state_type=state_type,
+            state_def=state_def,
+            comments=comments
+        )
+
+
+    def set_remove(self,body,key,comments="") -> State:
+        """Generates the `set_remove` state when a particular key is deleted.
+
+        Args:
+            body : The contents of the set that are to be sent along with the state
+            key : The key that has been deleted
+            comments (optional): The comments that are supposed to rendered with the state for descriptive purpose. Defaults to "".
+
+        Returns:
+            ARgorithmToolkit.utils.State: returns the ``set_remove`` state for the respective set mentioned
+        """
+        state_type = "set_remove"
+        state_def = {
+            "id" : self._id,
+            "variable_name" : self.name,
+            "body" : body.copy(),
+            "key" : key,
+        }
+        return State(
+            state_type=state_type,
+            state_def=state_def,
+            comments=comments
+        )
+
+    def set_find(self, body, key, found, comments="") -> State:
+        """Generates the `set_find` state when a particular key is searched for.
+
+        Args:
+            body : The contents of the set that are to be sent along with the state
+            key : The key that has been searched
+            found : true if found false if not found
+            comments (optional): The comments that are supposed to rendered with the state for descriptive purpose. Defaults to "".
+
+        Returns:
+            ARgorithmToolkit.utils.State: returns the ``set_find`` state for the respective set mentioned
+        """
+        state_type = "set_find"
+        state_def = {
+            "id": self._id,
+            "variable_name" : self.name,
+            "key" : key,
+            "found": found,
+            "body" : body.copy()
+        }
+        return State(
+            state_type=state_type,
+            state_def=state_def,
+            comments=comments
+        )
+
+@serialize
+class Set(ARgorithmStructure):
+    """The Set class used to emulate set datastructure that can be
+    rendered in the ARgorithm Application as series of unique keys.
+
+    Attributes:
+        name (str): name given to the rendered block in augmented reality. Essential. Should not be altered after initialisation
+        algo (ARgorithmToolkit.utils.StateSet): The stateset that will store the states generated by the instance of Set Class
+        data (Vector, Array) : to generate set from an existent list
+        comments (str,optional): Description of instance of set and its applications that will be rendered during the ``set_declare`` state.
+
+    Raises:
+        ARgorithmError: raised if name is not given or Stateset if not provided
+
+    Examples:
+        This is an example of set being declared
+
+        >>> algo = ARgorithmToolkit.StateSet()
+        >>> set1 = ARgorithmToolkit.Set(name='set1',algo=algo,data=[1,2,3,4,4,2,1])
+        >>> set1
+        Set({1,2,3,4})
+
+        The set generated supports all the functionality of default set
+
+        >>> len(set1)
+        4
+        >>> set1.find(2)
+        True
+        >>> set1.add("s")
+        >>> set1
+        Set({1, 2, 3, 4, "s"})
+        >>> for key in set1:
+        ...    print(key)
+        1
+        2
+        3
+        4
+        5
+        "s"
+        >>> set1.remove("s")
+        >>> set1
+        Set({1, 2, 3, 4})
+    """
+
+    def __init__(self, name:str, algo:StateSet, data:iterable=None, comments= ""):
+        try:
+            assert isinstance(name, str)
+            self.state_generator = SetState(name, str(id(self)))
+        except Exception as ex:
+            raise ARgorithmError('Give valid name to data structure') from ex
+        try:
+            assert isinstance(algo, StateSet)
+            self.algo = algo
+        except Exception as ex:
+            raise ARgorithmError("Set structure needs a reference of template to store states") from ex
+
+        self.body = set()
+        if data:
+            for x in data:
+                if isinstance(x, ARgorithmHashable):
+                    self.body.add(x.to_json())
+                elif isinstance(x, (int,str,bool,float,generic)):
+                    self.body.add(x)
+                else:
+                    raise TypeError("Invalid key error : Please provide data with ARgorithmHashable type or (int, float, bool, str)")
+        self.__working_set = set(data) if data else set()
+        state = self.state_generator.set_declare(self.body, comments=comments)
+        self.algo.add_state(state)
+
+    def __len__(self) -> int:
+        """returns size of Set when processed by len() function.
+
+        Returns:
+            int: size of the set
+
+        Example:
+            >>> set1
+            Set({1,2,3})
+            >>> len(set1)
+            3
+        """
+        return len(self.__working_set)
+
+
+    def add(self, key, comments=""):
+        """Adds a unique key to the set.
+        Args:
+            key (ARgorithmStructure or (int, str, float, bool)) : key to add to the set
+            comments (str, optional): Comments for descriptive purpose. Defaults to "".
+        Example:
+        >>> set1
+        Set({1,2})
+        >>> set1.add('abc')
+        Set({1,2,'abc'})
+        >>> set1.add(1)
+        >>> set1
+        Set({1,2,'abc'})
+        """
+        try:
+            assert isinstance(key,(ARgorithmHashable,int,bool,str,float))
+        except AssertionError as ae:
+            raise TypeError("Invalid key error : Please provide data with ARgorithmHashable type or (int, float, bool, str)") from ae
+        if isinstance(key, ARgorithmHashable):
+            self.body.add(key.to_json())
+        else:
+            self.body.add(key)
+
+        self.__working_set.add(key)
+        state = self.state_generator.set_add(self.body, key,comments)
+        self.algo.add_state(state)
+
+
+    def remove(self, key, comments=""):
+        """removes the key from the set
+        Args:
+            key (ARgorithmStructure or (int, str, float, bool)) : key to remove from the set
+            comments (str, optional): Comments for descriptive purpose. Defaults to "".
+
+        Example:
+            >>> set1
+            Set({1,2,3})
+            >>> set1.remove(1)
+            >>> set1
+            Set({2,3})
+        """
+        try:
+            if isinstance(key, ARgorithmHashable):
+                self.body.remove(key.to_json())
+            else:
+                self.body.remove(key)
+            self.__working_set.remove(key)
+            state = self.state_generator.set_remove(self.body, key,comments)
+            self.algo.add_state(state)
+        except Exception as e:
+            raise ARgorithmError(f"Invalid Key Error : {str(e)}") from e
+
+    def find(self, key, comments="") -> bool:
+        """finds if a key is present in the set
+        Args:
+            key (ARgorithmStructure or (int, str, float, bool)) : key to find in the set
+            comments (str, optional): Comments for descriptive purpose. Defaults to "".
+        Returns:
+            bool : true if key found else false
+
+        Example:
+            >>> set1
+            Set({1,2,"abc"})
+            >>> set1.find("abc")
+            True
+            >>> set1.find("abcd")
+            False
+        """
+        found = key in self.__working_set
+        state = self.state_generator.set_find(self.body, key, found,comments)
+        self.algo.add_state(state)
+        return found
+
+
+    def intersection(self, other, comments="") :
+        """Creates a new set with the intersection of the calling set with the set in the arguments provided
+        Args:
+            other (Set) : set to find the intersection with
+            comments (str, optional): comments for descriptive purpose. Defaults to "".
+
+        returns:
+            Set : intersection of self and other
+
+        example:
+            >>> set1
+            Set({1,2})
+            >>> set2
+            Set({2,3,4})
+            >>> set1.intersection(set2)
+            Set({2})
+        """
+        if not comments:
+            comments = f"Creating new set with intersection of {self.state_generator.name} and {other.state_generator.name}"
+        intersect_data = self.__working_set.intersection(other.__working_set) # pylint: disable=protected-access
+        intersect_name = f"{self.state_generator.name}_intersection_{other.state_generator.name}"
+        intersect = Set(intersect_name, self.algo, intersect_data, comments=comments)
+        return intersect
+
+    def union(self, other, comments="") :
+        """Creates a new set with the union of the calling set with the set in the arguments provided
+        Args:
+            other (Set) : set to find the union with
+            comments (str, optional): comments for descriptive purpose. Defaults to "".
+
+        returns:
+            Set : union of self and other
+
+        example:
+            >>> set1
+            Set({1,2})
+            >>> set2
+            Set({2,3,4})
+            >>> set1.union(set2)
+            Set({1,2,3,4})
+        """
+        if not comments:
+            comments = f"Creating new set with union of {self.state_generator.name} and {other.state_generator.name}"
+        union_data = self.__working_set.union(other.__working_set) # pylint: disable=protected-access
+        union_name = f"{self.state_generator.name}_union_{other.state_generator.name}"
+        _union = Set(union_name, self.algo, union_data, comments=comments)
+        return _union
+
+    def difference(self, other, comments="") :
+        """Creates a new set with the difference of the calling set with the set in the arguments provided
+        Args:
+            other (Set) : set to find the difference with
+            comments (str, optional): comments for descriptive purpose. Defaults to "".
+
+        returns:
+            Set : difference of self and other
+
+        example:
+            >>> set1
+            Set({1,2})
+            >>> set2
+            Set({2,3,4})
+            >>> set1.difference(set2)
+            Set({1})
+        """
+        if not comments:
+            comments = f"Creating new set with difference of {self.state_generator.name} and {other.state_generator.name}"
+        diff_data = self.__working_set.difference(other.__working_set) # pylint: disable=protected-access
+        diff_name = f"{self.state_generator.name}_difference_{other.state_generator.name}"
+        diff = Set(diff_name, self.algo, diff_data, comments=comments)
+        return diff
+
+    def __repr__(self) -> str:
+        """Return representation for shell outputs.
+
+        Returns:
+            str: shell representation for Set
+        """
+        empty = "{}"
+        return f"Set({self.__working_set.__repr__() if len(self.__working_set) > 0 else empty})"
+
+    def __str__(self) -> str:
+        """Return string conversion for Set
+
+        Returns:
+            str: string conversion for Set
+        """
+        empty = "{}"
+        return f"Set({self.__working_set.__str__() if len(self.__working_set) > 0 else empty})"
diff --git a/ARgorithmToolkit/stack.py b/ARgorithmToolkit/stack.py
index 016c2fd..1b092ae 100644
--- a/ARgorithmToolkit/stack.py
+++ b/ARgorithmToolkit/stack.py
@@ -7,7 +7,8 @@
     >>> st = ARgorithmToolkit.Stack(name="st",algo=algo)
 """
 
-from ARgorithmToolkit.utils import State, StateSet, ARgorithmError
+from ARgorithmToolkit.utils import State, StateSet, ARgorithmError, ARgorithmStructure
+from ARgorithmToolkit.encoders import serialize
 
 class StackState():
     """This class is used to generate states for various actions performed on
@@ -16,6 +17,7 @@ class StackState():
     Attributes:
 
         name (str) : Name of the variable for whom we are generating states
+        _id (str) : id of the variable for whom we are generating states
     """
 
     def __init__(self,name):
@@ -108,7 +110,8 @@ def stack_top(self,body,comments=""):
             comments=comments
         )
 
-class Stack:
+@serialize
+class Stack(ARgorithmStructure):
     """The Stack class is a container interface for the stack, a linear
     container implementation of LIFO.
 
diff --git a/ARgorithmToolkit/string.py b/ARgorithmToolkit/string.py
index 240d405..00acc69 100644
--- a/ARgorithmToolkit/string.py
+++ b/ARgorithmToolkit/string.py
@@ -7,8 +7,8 @@
     >>> s = ARgorithmToolkit.String(name="s",algo=algo)
 """
 
-
-from ARgorithmToolkit.utils import State, StateSet, ARgorithmError
+from ARgorithmToolkit.utils import ARgorithmHashable, State, StateSet, ARgorithmError, ARgorithmStructure
+from ARgorithmToolkit.encoders import serialize
 
 class StringState:
     """This class is used to generate states for various actions performed on
@@ -17,10 +17,12 @@ class StringState:
     Attributes:
 
         name (str) : Name of the variable for whom we are generating states
+        _id (str) : id of the variable for whom we are generating states
     """
 
-    def __init__(self, name):
+    def __init__(self, name, _id):
         self.name = name
+        self._id = _id
 
     def string_declare(self, body, comments=""):
         """Generates the `string_declare` state when an instance of string is
@@ -35,6 +37,7 @@ def string_declare(self, body, comments=""):
 
         state_type = "string_declare"
         state_def = {
+            "id" : self._id,
             "variable_name" : self.name,
             "body" : body
         }
@@ -58,6 +61,7 @@ def string_iter(self, body, index, comments=""):
         """
         state_type = "string_iter"
         state_def = {
+            "id" : self._id,
             "variable_name" : self.name,
             "body" : body,
             "index" : index
@@ -82,6 +86,7 @@ def string_append(self, body, element, comments=""):
         """
         state_type = "string_append"
         state_def = {
+            "id" : self._id,
             "variable_name" : self.name,
             "body" : body,
             "element" : element,
@@ -116,7 +121,8 @@ def __next__(self):
         self._index += 1
         return v
 
-class String():
+@serialize
+class String(ARgorithmStructure, ARgorithmHashable):
     """The String class is a wrapper around the already existing string class
     in python adding the feature to store states.
 
@@ -138,7 +144,8 @@ class String():
     def __init__(self,name,algo,body='',comments=""):
         try:
             assert isinstance(name,str)
-            self.state_generator = StringState(name)
+            self._id = str(id(self))
+            self.state_generator = StringState(name, self._id)
         except AssertionError as e:
             raise ARgorithmError('Give valid name to data structure') from e
         try:
diff --git a/ARgorithmToolkit/utils.py b/ARgorithmToolkit/utils.py
index c9751f0..22c3ff5 100644
--- a/ARgorithmToolkit/utils.py
+++ b/ARgorithmToolkit/utils.py
@@ -101,7 +101,16 @@ def add_comment(self,comments:str):
         )
         self.add_state(comment_state)
 
-class Variable:
+class ARgorithmHashable:
+    """Interface from which main classes for datastructures can inherit to make them hashable in Set and Map implementations.
+    This interface will enable different classes to be keys in Map(hash-map) and Set(hash-set) implementations.
+    """
+
+class ARgorithmStructure:
+    """Interface from which main classes for datastructures. This interface enables different classes to be a values in Map(hash-map) implementations.
+    """
+
+class Variable(ARgorithmStructure, ARgorithmHashable):
     """Some programs might need us to listen and store states of primitive
     datatypes like int, str , bool etc. For tha purpose, we have the Variable
     class.
@@ -123,8 +132,10 @@ def __init__(self,name:str,algo:StateSet,value=None,comments=""):
         self.name = name
         self.__flag = False
         self.value = value
+        self._id = str(id(self))
         state_type = "variable_declare"
         state_def = {
+            "id" : self._id,
             "variable_name" : name ,
             "value" : value
         }
@@ -148,6 +159,7 @@ def __setattr__(self,key,value):
         if(key == 'value' and self.__flag):
             state_type = "variable_highlight"
             state_def = {
+                "id" : self._id,
                 "variable_name" : self.name,
                 "value" : self.value,
             }
diff --git a/ARgorithmToolkit/vector.py b/ARgorithmToolkit/vector.py
index a0b3be8..eec27e9 100644
--- a/ARgorithmToolkit/vector.py
+++ b/ARgorithmToolkit/vector.py
@@ -8,7 +8,9 @@
     >>> vec = ARgorithmToolkit.vector.Vector(name='vec',algo=algo)
 """
 
-from ARgorithmToolkit.utils import State, StateSet, ARgorithmError
+from ARgorithmToolkit.utils import State, StateSet, ARgorithmError, ARgorithmStructure
+from ARgorithmToolkit.encoders import serialize
+
 class VectorState:
     """This class is used to generate states for various actions performed on
     the ``ARgorithmToolkit.vector.Vector`` object.
@@ -17,8 +19,9 @@ class VectorState:
 
         name (str) : Name of the variable for whom we are generating states
     """
-    def __init__(self,name):
+    def __init__(self,name,_id):
         self.name = name
+        self._id = _id
 
 
     def vector_declare(self,body,comments=""):
@@ -34,6 +37,7 @@ class is created.
         """
         state_type = "vector_declare"
         state_def = {
+            "id" : self._id,
             "variable_name" : self.name,
             "body" : list(body)
         }
@@ -59,6 +63,7 @@ def vector_iter(self,body,index,value=None,last_value=None,comments=""):
         """
         state_type = "vector_iter"
         state_def = {
+            "id" : self._id,
             "variable_name" : self.name,
             "body" : list(body),
             "index" : index
@@ -86,6 +91,7 @@ def vector_remove(self,body,index , comments=""):
         """
         state_type = "vector_remove"
         state_def = {
+            "id" : self._id,
             "variable_name" : self.name,
             "body" : list(body),
             "index" : index
@@ -111,6 +117,7 @@ def vector_insert(self,body,element,index,comments=""):
         """
         state_type = "vector_insert"
         state_def = {
+            "id" : self._id,
             "variable_name" : self.name,
             "body" : list(body),
             "element" : element,
@@ -136,6 +143,7 @@ def vector_swap(self,body,indexes,comments=""):
         """
         state_type = "vector_swap"
         state_def = {
+            "id" : self._id,
             "variable_name" : self.name,
             "body" : list(body),
             "index1" : indexes[0],
@@ -161,6 +169,7 @@ def vector_compare(self,body,indexes,comments=""):
         """
         state_type = "vector_compare"
         state_def = {
+            "id" : self._id,
             "variable_name" : self.name,
             "body" : list(body),
             "index1" : indexes[0],
@@ -195,7 +204,8 @@ def __next__(self):
         self._index += 1
         return v
 
-class Vector:
+@serialize
+class Vector(ARgorithmStructure):
     """The Vector class provides a wrapped around the python list class to
     emulate it as a vector.
 
@@ -217,7 +227,8 @@ class Vector:
     def __init__(self,name,algo,data=None,comments=""):
         try:
             assert isinstance(name,str)
-            self.state_generator = VectorState(name)
+            self._id = str(id(self))
+            self.state_generator = VectorState(name, self._id)
         except AssertionError as e:
             raise ARgorithmError('Give valid name to data structure') from e
         try:
diff --git a/MANIFEST.in b/MANIFEST.in
index 05cba9e..76d8389 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,7 +1,8 @@
 include pyproject.toml
 
-# Include the README
-include *.md
-
 # Include the license file
-include LICENSE.txt
\ No newline at end of file
+include LICENSE.txt
+
+# Include the package data
+include ARgorithmToolkit/data/config.schema.json
+include ARgorithmToolkit/data/template.py
\ No newline at end of file
diff --git a/designs/array.design.yml b/designs/array.design.yml
index f35f169..8ead25a 100644
--- a/designs/array.design.yml
+++ b/designs/array.design.yml
@@ -6,12 +6,14 @@ states:
   - array_declare:
       description : creates new array
       definition:
+        id : id of the datastructure
         variable_name: The name of the array [required]
         body: contents of the array [required]
   
   - array_iter:
       description : highlight element to indicate iteration
       definition:
+        id : id of the datastructure
         variable_name: The name of the array [required]
         body: contents of the array after the operation [required]
         index : index at which element has to be highlighted [reqiured]
@@ -21,6 +23,7 @@ states:
   - array_compare:
       description : highlight elements to indicate comparision
       definition:
+        id : id of the datastructure
         variable_name: The name of the array [required]
         body: contents of the array after the operation [required]
         index_1 : first index at which element has to be highlighted [required]
@@ -29,6 +32,7 @@ states:
   - array_swap:
       description : highlight elements to indicate swap
       definition:
+        id : id of the datastructure
         variable_name: The name of the array [required]
         body: contents of the array after the operation [required]
         index_1 : first index at which element has to be highlighted [required]
diff --git a/designs/doublylinkedlist.design.yml b/designs/doublylinkedlist.design.yml
index 1e2bdaa..b68b62f 100644
--- a/designs/doublylinkedlist.design.yml
+++ b/designs/doublylinkedlist.design.yml
@@ -6,6 +6,7 @@ states:
   - dllnode_declare:
         description: Indicates that a new Node has been created
         definition:
+          id : id of the datastructure
           variable_name: The id of the doubly doubly linked list Node
           value: The value in the node
           next: The id of the next doubly doubly linked list node. Default "none"
@@ -14,6 +15,7 @@ states:
   - dllnode_iter:
         description: Highlights an node in case the value is changed
         definition:
+          id : id of the datastructure
           variable_name: The id of the doubly doubly linked list Node
           value: The value in the node
           last_value : the value of the data in the node before it was changed
@@ -23,6 +25,7 @@ states:
   - dllnode_next:
         description: Indicates that the reference to next node has been changed
         definition:
+          id : id of the datastructure
           variable_name: The id of the doubly doubly linked list Node
           value: The value in the node
           next: The id of the next doubly doubly linked list node. Default "none"
@@ -31,11 +34,13 @@ states:
   - dllnode_delete:
         description: Deletes the node
         definition:
+          id : id of the datastructure
           variable_name: The id of the doubly doubly linked list Node
        
   - dll_declare:
         description: Creates a head pointer for start of doubly doubly linked list
         definition:
+          id : id of the datastructure
           variable_name: The id of the doubly doubly linked list Node
           head: The id of the head doubly doubly linked list node. Default "none"
           tail: The id of the tail doubly doubly linked list node. Default "none"
@@ -43,6 +48,7 @@ states:
   - dll_head:
         description: Changes head pointer of doubly doubly linked list
         definition:
+          id : id of the datastructure
           variable_name: The id of the doubly doubly linked list Node
           head: The id of the head doubly doubly linked list node. Default "none"
           tail: The id of the tail doubly doubly linked list node. Default "none"
diff --git a/designs/linkedlist.design.yml b/designs/linkedlist.design.yml
index d231ca6..d73a74f 100644
--- a/designs/linkedlist.design.yml
+++ b/designs/linkedlist.design.yml
@@ -6,6 +6,7 @@ states:
   - llnode_declare:
         description: Indicates that a new Node has been created
         definition:
+          id : id of the datastructure
           variable_name: The id of the linkedlist Node
           value: The value in the node
           next: The id of the next linkedlist node. Default "none"
@@ -13,6 +14,7 @@ states:
   - llnode_iter:
         description: Highlights an node in case the value is changed
         definition:
+          id : id of the datastructure
           variable_name: The id of the linkedlist Node
           value: The value in the node
           last_value : value of the data in the node before it was changed
@@ -21,6 +23,7 @@ states:
   - llnode_next:
         description: Indicates that the reference to next node has been changed
         definition:
+          id : id of the datastructure
           variable_name: The id of the linkedlist Node
           value: The value in the node
           next: The id of the next linkedlist node. Default "none"
@@ -28,17 +31,20 @@ states:
   - llnode_delete:
         description: Deletes the node
         definition:
+          id : id of the datastructure
           variable_name: The id of the linkedlist Node
        
   - ll_declare:
         description: Creates a head pointer for start of singly linkedlist
         definition:
+          id : id of the datastructure
           variable_name: The id of the linkedlist Node
           head: The id of the head linkedlist node. Default "none"
   
   - ll_head:
         description: Changes head pointer of singly linkedlist
         definition:
+          id : id of the datastructure
           variable_name: The id of the linkedlist Node
           head: The id of the head linkedlist node. Default "none"
   
diff --git a/designs/map_design.yml b/designs/map_design.yml
new file mode 100644
index 0000000..0b5b613
--- /dev/null
+++ b/designs/map_design.yml
@@ -0,0 +1,92 @@
+date: '2021-02-07'
+category: Map
+author: Yatharth Mathur
+
+states: 
+  - map_declare:
+      description : creates new map
+      definition:
+        id : id of the datastructure
+        variable_name : The name of the map [required]
+        body : dict with object_id to object_id mapping or key to value mapping [required]
+  
+  - map_get:
+    description : get the value for the key
+    definition:
+      id : id of the datastructure
+      variable_name : name of the map [required]
+      body : dict with object_id to object_id mapping or key to value mapping [required]
+      key : object reference or key to access value for
+      value : value / object reference at the given key
+
+  - map_set:
+    description : set the value for the given key
+    definition :
+      id : id of the datastructure
+      variable_name : name of the map [required]
+      body : dict with object_id to object_id mapping or key to value mapping [required]
+      key : object reference or key to access value for
+      value : value / object reference at the given key
+      last_value : value / object reference at the last key
+
+  - map_remove:
+    description : remove the entry for the given key
+    definition :
+      id : id of the datastructure
+      variable_name : name of the map [required]
+      body : dict with object_id to object_id mapping or key to value mapping [required]
+      key : object reference or key to access value for
+      value : value / object reference at the given key
+
+        
+classes:
+  - ARgorithmToolkit.map.Map:
+      description: Class that manages the map interface
+  - ARgorithmToolkit.map.MapState:
+      description: State template manager for map related states
+  - ARgorithmToolkit.map.MapIterator:
+      description: Iterator for the map class
+
+functions:
+  - initialize:
+      description: create new map
+      function:
+        name: ARgorithmToolkit.map.Map.__init__
+        parameters:
+          required:
+            - algo
+      state: map_declare
+        
+  - get:
+      description: return map item by key
+      function:
+        name: ARgorithmToolkit.set.Set.__getitem__
+        parameters:
+          required:
+            - key
+      state: map_get
+
+  - iterator:
+      description: returns a iterator object for the map
+      function: 
+        name: ARgorithmToolkit.map.Map.__iter__
+      state: None
+ 
+  - set:
+    description: sets the value to a specific key
+    function: 
+      name: ARgorithmToolkit.map.Map.__setitem__
+    state: map_set
+
+  - remove:
+    description: removes a key/value entry from map
+    function:
+      name: ARgorithmToolkit.map.Map.__delitem__
+    state: map_remove
+  
+
+  - size:
+    description: returns the size of the dictionary (number of key/value pairs)
+    function:
+      name: ARgorithmToolkit.map.Map.__len__
+    state: None
\ No newline at end of file
diff --git a/designs/priorityqueue.design.yml b/designs/priorityqueue.design.yml
index 5562bc9..d924c1f 100644
--- a/designs/priorityqueue.design.yml
+++ b/designs/priorityqueue.design.yml
@@ -6,18 +6,21 @@ states:
     - priorityqueue_declare:
         description: Creates a queue
         definition:
+            id : id of the datastructure
             variable_name: Variable name of the priorityqueue [required]
             body : body if non-empty , default empty
     
     - priorityqueue_poll:
         description: Pops item with the least priority
         definition:
+            id : id of the datastructure
             variable_name: Variable name of the priorityqueue [required]
             body: body after operation
 
     - priorityqueue_offer:
         description: Push item according to its priority
         definition:
+            id : id of the datastructure
             variable_name: Variable name of the priorityqueue [required]
             body : body after operation [required]
             element: element to be pushed [required]
@@ -25,6 +28,7 @@ states:
     - priorityqueue_peek:
         description : highlight the top of the priority queue
         definition:
+            id : id of the datastructure
             variable_name: Variable name of the queue [required]
             body: body of priorityqueue
 
diff --git a/designs/queue.design.yml b/designs/queue.design.yml
index 280b4e3..18ef083 100644
--- a/designs/queue.design.yml
+++ b/designs/queue.design.yml
@@ -6,18 +6,21 @@ states:
     - queue_declare:
         description: Creates a queue
         definition:
+            id : id of the datastructure
             variable_name: Variable name of the queue [required]
             body : body if non-empty , default empty
     
     - queue_pop:
         description: Pop front item
         definition:
+            id : id of the datastructure
             variable_name: Variable name of the queue [required]
             body: body after operation
 
     - queue_push:
         description: Push item to the back of the queue
         definition:
+            id : id of the datastructure
             variable_name: Variable name of the queue [required]
             body : body after operation [required]
             element: element to be pushed [required]
@@ -25,12 +28,14 @@ states:
     - queue_front:
         description : highlight front item
         definition:
+            id : id of the datastructure
             variable_name: Variable name of the queue [required]
             body: body of queue
 
     - queue_back:
         description : highlight back item
         definition:
+            id : id of the datastructure
             variable_name: Variable name of the queue [required]
             body: body of queue
 
diff --git a/designs/set_design.yml b/designs/set_design.yml
new file mode 100644
index 0000000..11a8a72
--- /dev/null
+++ b/designs/set_design.yml
@@ -0,0 +1,109 @@
+date: '2021-02-09'
+category: Set
+author: Yatharth Mathur
+
+states: 
+  - set_declare:
+      description : creates new set
+      definition:
+        id : id of the datastructure
+        variable_name : The name of the set [required]
+        body : list with elements inside working set [required]
+        init_list : list with objects to add to set [optional]
+  
+  - set_add:
+    description : add new element to the set
+    definition :
+      id : id of the datastructure
+      variable_name : The name of the set [required]
+      body : list with elements inside working set [required]
+      key : key to be added in the set
+
+  - set_remove:
+    description : remove key from the set
+    definition :
+      id : id of the datastructure
+      variable_name : The name of the set [required]
+      body : list with elements inside working set [required]
+      key : key to be remove in the set [required]
+
+  - set_find:
+    description : lookup key in set
+    definition : 
+      id : id of the datastructure
+      variable_name : The name of the set [required]
+      body : list with elements inside working set [required]
+      key : key being looked up in the set [required]
+      found : true if found else false
+
+        
+classes:
+  - ARgorithmToolkit.set.Set:
+      description: Class that manages the set interface
+  - ARgorithmToolkit.set.SetState:
+      description: State template manager for set related states
+
+functions:
+  - initialize:
+      description: create new set
+      function:
+        name: ARgorithmToolkit.set.Set.__init__
+        parameters:
+          required:
+            - algo
+      state: set_declare
+        
+  - add:
+      description: add new key to set
+      function:
+        name: ARgorithmToolkit.set.Set.add
+        parameters:
+          required:
+            - key
+      state: set_add
+
+  - remove:
+    description: removes a key entry from set
+    function:
+      name: ARgorithmToolkit.set.Set.remove
+      parameters:
+          required:
+            - key
+    state: set_remove
+
+  - find:
+    description: lookup key in set
+    function:
+      name: ARgorithmToolkit.set.Set.find
+      parameters:
+          required:
+            - key
+    state: set_lookup
+
+  - intersection:
+    description: find and create new set with intersection of the two sets
+    function:
+      name: ARgorithmToolkit.set.Set.intersection
+      parameters:
+        required:
+          - B (Set)
+    state: set_declare
+
+  - union:
+    description: find and create new set with union of the two sets
+    function:
+      name: ARgorithmToolkit.set.Set.union
+      parameters:
+        required:
+          - B (Set)
+    state: set_declare
+
+  - difference:
+    description: find and create new set with difference of the two sets
+    function:
+      name: ARgorithmToolkit.set.Set.difference
+      parameters:
+        required:
+          - B (Set)
+    state: set_declare
+  
\ No newline at end of file
diff --git a/designs/stack.design.yml b/designs/stack.design.yml
index 44a9ef7..6fcfbc7 100644
--- a/designs/stack.design.yml
+++ b/designs/stack.design.yml
@@ -6,12 +6,14 @@ states:
     - stack_declare:
         description: Creates a stack
         definition:
+            id : id of the datastructure
             variable_name: Variable name of the stack [required]
             body : body if non-empty , default empty
 
     - stack_push:
         description: Push item onto stack
         definition:
+            id : id of the datastructure
             variable_name: Variable name of the stack [required]
             body : body after operation [required]
             element: element to be pushed [required]
@@ -19,12 +21,14 @@ states:
     - stack_pop:
         description: Pop topmost item
         definition:
+            id : id of the datastructure
             variable_name: Variable name of the stack [required]
             body: body after operation
             
     - stack_top:
         description : highlight top item
-        definition:
+        definition: 
+            id : id of the datastructure
             variable_name: Variable name of the stack [required]
             body: body of stack
   
diff --git a/designs/string.design.yml b/designs/string.design.yml
index 746cda9..5837053 100644
--- a/designs/string.design.yml
+++ b/designs/string.design.yml
@@ -6,12 +6,14 @@ states:
   - string_declare:
       description : creates new string
       definition:
+        id : id of the datastructure
         variable_name: The name of the string [required]
         body: contents of the string [required]
 
   - string_append:
       description : to insert element at the end of the string
       definition:
+        id : id of the datastructure
         variable_name: The name of the string [required]
         body: contents of the string after the operation [required]
         element : element to be added [required]
@@ -19,6 +21,7 @@ states:
   - string_iter:
       description : highlight element to indicate iteration
       definition:
+        id : id of the datastructure
         variable_name: The name of the string [required]
         body: contents of the string after the operation [required]
         index : index at which element has to be highlighted [reqiured]
diff --git a/designs/variable.design.yml b/designs/variable.design.yml
index 53da2d0..afd9848 100644
--- a/designs/variable.design.yml
+++ b/designs/variable.design.yml
@@ -6,12 +6,14 @@ states:
   - variable_declare:
       description : creates a instance of a int , char or boolean
       definition:
+        id : id of the datastructure
         variable_name: name of the variable [required] 
         value: value [required]
   
   - variable_highlight:
       description : highlights the variable and records the changes done to it.
       definition:
+        id : id of the datastructure
         variable_name: name of the variable [required] 
         last_value: value of the variable before it was changed [required]
         value: value [required]
diff --git a/designs/vector.design.yml b/designs/vector.design.yml
index be3119d..3b69b08 100644
--- a/designs/vector.design.yml
+++ b/designs/vector.design.yml
@@ -6,12 +6,14 @@ states:
   - vector_declare:
       description : creates new vector
       definition:
+        id : id of the datastructure
         variable_name: The name of the vector [required]
         body: contents of the vector [required]
 
   - vector_insert:
       description : to insert or assign elements
       definition:
+        id : id of the datastructure
         variable_name: The name of the vector [required]
         body: contents of the vector after the operation [required]
         element : element to be added [required]
@@ -20,6 +22,7 @@ states:
   - vector_remove:
       description : to remove element 
       definition:
+        id : id of the datastructure
         variable_name: The name of the vector [required]
         body: contents of the vector after the operation [required]
         index : index at which element has to be removed [required]
@@ -27,6 +30,7 @@ states:
   - vector_iter:
       description : highlight element to indicate iteration and records the changes done to the element
       definition:
+        id : id of the datastructure
         variable_name: The name of the vector [required]
         body: contents of the vector after the operation [required]
         index : index at which element has to be highlighted [required]
@@ -36,6 +40,7 @@ states:
   - vector_compare:
       description : highlight elements to indicate comparision
       definition:
+        id : id of the datastructure
         variable_name: The name of the vector [required]
         body: contents of the vector after the operation [required]
         index_1 : first index at which element has to be highlighted [required]
@@ -44,6 +49,7 @@ states:
   - vector_swap:
       description : highlight elements to indicate swap
       definition:
+        id : id of the datastructure
         variable_name: The name of the vector [required]
         body: contents of the vector after the operation [required]
         index_1 : first index at which element has to be highlighted [required]
diff --git a/docs/docs/CHANGELOG.md b/docs/docs/CHANGELOG.md
index 7be1922..793b601 100644
--- a/docs/docs/CHANGELOG.md
+++ b/docs/docs/CHANGELOG.md
@@ -1,3 +1,13 @@
+## 0.2.0
+
+- Map and Set implementation
+- Serialisation feature added for nested ARgorithmStructures
+- Verification of files before submission to server
+- Updated designs for all data structures focussing on object ID
+- Updated config file format
+- Added CLI client for generating config files
+- user input for testing argorithms hosted on servers
+
 ### 0.1.1
 
 - Fixed bug in Linkedlist and DoublyLinked list dealing with None references
diff --git a/docs/docs/cli.md b/docs/docs/cli.md
index 4116f5a..796f1c7 100644
--- a/docs/docs/cli.md
+++ b/docs/docs/cli.md
@@ -22,7 +22,7 @@ Options:
 ```
 </div>
 
-## Configure
+## Connect
 
 This command can be used to set your own server IP. All your requests will be sent to this IP. If you are running server locally you dont need to configure IP, instead you can use the `-l` or `--local` flag to connect to local servers.
 
@@ -34,7 +34,7 @@ This command can be used to set your own server IP. All your requests will be se
 
 <div class="termy">
 ```console
-$ ARgorithm configure
+$ ARgorithm connect
 # Enter server endpoint :$ http://myserverendpoint.com 
 [SUCCESS]: CONNECTED
 Cloud requests will now go to http://myserverendpoint.com
@@ -97,7 +97,7 @@ refer documentation at https://argorithm.github.io/toolkit/ to learn how to use
 chech out examples at https://github.com/ARgorithm/toolkit/tree/master/examples
 
 $ ls
-hello_world.config.json	hello_world.py
+hello_world.py
 ```
 </div>
 
@@ -115,6 +115,9 @@ The files generated are shown below
 
         return algo
 ```
+
+If you use the `--config` flag it will generate a `<name>.config.json` file. You can also try the [`configure`](#configure) command
+
 **hello_world.config.json**
 ```json
 {
@@ -127,6 +130,53 @@ The files generated are shown below
 }
 ```
 
+## Configure
+
+The configure command can be used to start the CLI based Config Generator. This allows users to easily create config files step by step
+
+<div class="termy">
+```console
+$ ARgorithm configure hello_world
+# Start CLI config generator?  [y/N]:$ y
+
+    +-----------------------------+
+    |  ARGORITHM CONFIG GENERATOR |
+    +-----------------------------+
+
+ARgorithmID: hello_world
+Codefile found: hello_world.py
+# which function should be called [run]:$ 
+# Enter ARgorithm Description:$ hello world application
+
+Setting up parameters for your argorithm
+input keywords are used to map the input passed to your function as kwargs
+
+# Do you want to another input keyword [y/N]:$ y
+
+add details for parameter
+# Enter parameter name:$ name
+# Enter parameter type:$ STRING
+# Enter parameter description:$ name of user
+
+# Do you want to set a size constraint to name [y/N]:$ n
+# Do you want to add parameter? [y/N]:$ n
+
+
+ENTER INPUT FOR ARGORITHM
+Based on argorithm parameters, input will be taken
+
+input keyword: name
+Description: name of user
+# Enter string value:$ Alan
+
+```
+</div>
+
+The `configure` should be used only after you are done programming. You can check out the config schema [here](/toolkit/tutorials/config)
+
+!!!warning
+	The simulation here might be different according to your function code.
+
 ## Submit
 
 The submit command is used to submit new ARgorithm to server. This comand takes the name of the argorithm for eg: `fibonacci`. In this case , it will search for `fibonacci.py` and `fibonacci.config.json` and after verification send them to server.
@@ -169,7 +219,7 @@ $ ARgorithm update fibonacci
 
 ## Test
 
-The test command is used to run the argorithms in the server and observe the states. Here the states are not being printed as that can be long output. You can print the the states in json format using the `--output` or `-o` option.
+The test command is used to run the argorithms in the server and observe the states. Here the states are not being printed as that can be long output. You can print the the states in json format using the `--output` or `-o` option. By default, the data given in the configuration example is taken as input. By using the `--user-input` flag you can enter your own input to the argorithm. 
 
 <div class="termy">
 ```console
diff --git a/docs/docs/server.md b/docs/docs/server.md
index 3785b56..fb8ba79 100644
--- a/docs/docs/server.md
+++ b/docs/docs/server.md
@@ -12,8 +12,8 @@ The server is built using FastAPI. The requirements for running the application
 
 - Python 3.6+
   - fastapi
-  - uvicorn
-  - gunicorn (for production use)
+  - uvicorn[standard]
+  - gunicorn
   - jinja2
   - aiofiles
   - python-multipart
@@ -21,8 +21,13 @@ The server is built using FastAPI. The requirements for running the application
   - python-jose
   - passlib[bcrypt]
   - motor
+  - tornado
+  - dnspython
+  - pytest
   - ARgorithmToolkit
   - PyJWT
+  - aioredis
+  - prometheus-client
 
 To run it in production, use gunicorn to run as a production server. Docker-ce will be required if server image is being used
 
@@ -57,13 +62,13 @@ Status: Downloaded new image alanjohn/argorithm-server
 
 The application can be run in different modes
 
-1. In-app database
+#### In-app database
 
-   No authentication or authorization services. Data stored using sqlite database. By default, it runs in this mode
+No authentication or authorization services. Data stored using sqlite database. By default, it runs in this mode
 
-2. mongodb database
+#### mongodb database
 
-   No authentication or authorization services. Data stored in mongodb database of your choice. For this you will need to set some environment variables:
+No authentication or authorization services. Data stored in mongodb database of your choice. For this you will need to set some environment variables:
 
    - `DATABASE=mongodb`
    - `DB_USERNAME=yourdbusername`
@@ -74,14 +79,33 @@ The application can be run in different modes
 !!! info
     If using a cloud mongo database like atlas which provides mongo+srv url as endpoint, you just need to paste that URL as your `DB_ENDPOINT`. You can ignore the `DB_USERNAME` and `DB_PASSWORD` env variables.
 
-3. mongodb with auth
+#### mongodb with auth
 
-   Authorization on all basic routes. Data stored in mongodb database of your choice. This is an enhancement to the previous mode so along with the required envs previously.
+Authorization on all basic routes. Data stored in mongodb database of your choice. This is an enhancement to the previous mode so along with the required envs previously.
 
    - `SECRET_KEY=yoursecretkey`
    - `ADMIN_EMAIL=sample@email.com`
    - `ADMIN_PASSWORD=test123`
 
+#### caching
+
+Caching on state generation when execution request comes on `/argorithms/run`. Uses [redis](https://redis.io) for implementing LRU cache. The following environment variables have to be set
+
+   - `CACHING=ENABLED`
+   - `REDIS_HOST=redis`
+   - `REDIS_PORT=6379`
+   - `REDIS_PASSWORD=notmypassword`
+
+#### monitoring
+
+By default, [prometheus](https://prometheus.io) metrics have been implemented and can be accessed at `/metrics` route. Programmer can secure the route by using the `METRICS_TOKEN` environment variable to add authorization bearer token. If not given then by default, there is no authorization required
+
+   - `METRICS_TOKEN=yourmetricstoken`
+
+You can check out the grafana folder in the code repository for a ARgorithm specific dashboard
+
+### Docker-compose examples
+
 Check the `Dockerfile` for the default values of these environment variables.
 The repo comes with two docker compose configuration files
 
@@ -101,9 +125,12 @@ The repo comes with two docker compose configuration files
 
     ```
     
-- `docker-compose.prod.yml` : runs application with mongodb and auth and will setup mongodb database as well. will read env variables from `.env` file
+- `docker-compose.prod.yml` : runs application with mongodb and auth and will setup mongodb database. A redis server is launched to handle caching and prometheus and grafana nodes are created for monitoring It will read environment variables from `.env` file
 
     ```yaml
+    # Sets up multiple services to demonstrate how a server cluster would run with cloud storage, authorization, caching and monitoring
+    # This file requires the existense of .env with neccessary variable
+    # The docker-compose file is added for emulation of how the application can be setup with full functionality
     version: "3"
     services:
         mongodb:
@@ -115,6 +142,13 @@ The repo comes with two docker compose configuration files
                 - MONGO_INITDB_ROOT_PASSWORD=${DB_PASSWORD}
             volumes:
                 - mongo-data:/data/db
+        redis:
+            image: redis
+            ports:
+                - 6379:6379
+            volumes:
+                - ./redis.conf:/usr/local/etc/redis/redis.conf
+            command: redis-server /usr/local/etc/redis/redis.conf
         arserver:
             image: alanjohn/argorithm-server:latest
             ports: 
@@ -127,24 +161,54 @@ The repo comes with two docker compose configuration files
                 - DB_PASSWORD=${DB_PASSWORD}
                 - DB_ENDPOINT=mongodb
                 - DB_PORT=27017
-                - ADMIN_EMAIL=${ADMIN_EMAIL}
-                - ADMIN_PASSWORD=${ADMIN_PASSWORD}
-            volumes:
-                - local-uploads:/tmp/argorithm
-    volumes:
-        mongo-data:
-            driver: local
-        uploads:
-            driver: local
-    ```
-
-	The environment variables in above compose files are read from `.env` file.You can create strong secret keys using
+            - ADMIN_EMAIL=${ADMIN_EMAIL}
+	            - ADMIN_PASSWORD=${ADMIN_PASSWORD}
+	            - CACHING=ENABLED
+	            - REDIS_HOST=redis
+	            - REDIS_PORT=6379
+	            - REDIS_PASSWORD=notmypassword
+	        volumes:
+	            - uploads:/tmp/argorithm
+	        depends_on:
+	            - mongodb
+	            - redis
+	    prometheus:
+	        image: prom/prometheus
+	        ports:
+	        - 9090:9090
+	        command:
+	        - --config.file=/etc/prometheus/prometheus.yml
+	        volumes:
+	        - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
+	        depends_on:
+	        - arserver
+	    grafana:
+	        image: grafana/grafana
+	        ports:
+	        - 3000:3000
+	        volumes:
+	        - ./grafana/datasource.yml:/etc/grafana/provisioning/datasource.yml
+	        env_file:
+	        - ./grafana/config.monitoring
+	        depends_on:
+	        - prometheus
+	volumes:
+	    mongo-data:
+	        driver: local
+	    uploads:
+	        driver: local
+	
+	```
+
+The environment variables in above compose files are read from `.env` file.You can create strong secret keys using
 
 <div class="termy">
+
 ```console
 $ openssl rand -hex 32
 09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7
 ```
+
 </div>
 
 ## Running the server
@@ -195,6 +259,8 @@ Attaching to server_mongodb_1,server_arserver_1
     - `Programmer`
     - `User`
 
-3. The programmer account allows you to create and manage argorithms. The user account allows you to run argorithms and get states. When using the CLI [account new](\cli#new) command, it create both a progammer and a user account for that email. The mobile application can only create user accounts.
+3. The programmer account allows you to create and manage argorithms. The user account allows you to run argorithms and get states. When using the CLI [account new](/toolkit/cli#new) command, it create both a progammer and a user account for that email. The mobile application can only create user accounts.
+
+4. logs are generated in server.log file which you will find in `/tmp/argorithm`. The `server.log` file contains request based logs for every path.
 
-4. logs are generated in server.log file which you will find in `\uploads`. The `server.log` file contains request based logs for every path. The `process.log` has logs regarding state generation for argorithm.
\ No newline at end of file
+5. Application metrics are available at `/metrics`
\ No newline at end of file
diff --git a/docs/docs/start.md b/docs/docs/start.md
index 3459c6f..6cb03d4 100644
--- a/docs/docs/start.md
+++ b/docs/docs/start.md
@@ -21,14 +21,11 @@ refer documentation at https://argorithm.github.io/toolkit/ to learn how to use
 chech out examples at https://github.com/ARgorithm/toolkit/tree/master/examples
 
 $ ls
-hello_world.config.json  hello_world.py
+hello_world.py
 ```
 </div>
 
-This will generate your `.py` file and your `.config.json` file.
-
-1.  The  `<name>.py` file will store your code that you will submit to the server hosting all ARgorithms
-2.  The `<name>.config.json`  stores important details about your ARgorithm such as its purpose and parameters required
+This will generate your `.py` file. The  `<name>.py` file will store your code that you will submit to the server hosting all ARgorithms
 
 The `<name>.py` file initially looks like this
 
@@ -48,22 +45,30 @@ def run(**kwargs):
 You can add whatever code you want to this file using all the tools and classes present in ARgorithmToolkit but be sure that
 
 1. Your file should have one function which takes `**kwargs` input (refer [here](https://book.pythontips.com/en/latest/args_and_kwargs.html) to know more about kwargs) that will should perform whatever you desire and should return the stateset. You can check out later in the document on how to use this stateset
-2.  you can create classes and additional functions in your code. Support for importing external modules is not yet added so its advisable not to add those.
+2.  you can create classes and additional functions in your code. Support for importing external modules is not yet added so its advisable not to use those.
+
+Once you have created your code, you need to create a `<name>.config.json` in which you will describe metadata regarding your argorithm. You can create a blank config file by using the `--config` flag in `init` command and enter your values. You can also create a `.config.json` later using the `configure` command.
 
-the `<name>.config.json` file is a JSON file storing all the metadata
+the `<name>.config.json` file is a JSON file storing all the metadata. Below is an example of the config.json for [bubblesort](/toolkit/tutorials/bubblesort). You can understand the `.config.json` file [here](/toolkit/tutorials/config)
 
 ```json
 {
-    "argorithmID" : "<name>",
-    "file" : "<name>.py",
-    "function" : "<function to be called>",
-    "parameters" : {
-        "variable-name" : "<data-type>"
-    } , 
-    "default" : {
-        "variable-name" : "<value>"
-    },
-    "description" : "Tell us about your ARgorithm"
+    "argorithmID": "bubblesort", 
+    "file": "bubblesort.py", 
+    "function": "run", 
+    "parameters": {
+        "array" : {
+            "description" : "Array to be sorted",
+            "type" : "ARRAY",
+            "item-type" : "INT"
+        }
+    }, 
+    "example": {
+        "array" : [
+            6,3,2,4,5,1
+        ]
+    }, 
+    "description": "demonstrate bubble sort"
 }
 ```
 
@@ -73,7 +78,7 @@ the `<name>.config.json` file is a JSON file storing all the metadata
 | file        | The file containing your codefile                            |
 | function    | The function that is going to be called                      |
 | parameters  | the parameters that your ARgorithm would need, this helps in anyone using your ARgorithm to understand what is the input format |
-| default     | default parameters in case no parameters are passed          |
+| example     | default parameters in case no parameters are passed          |
 | description | The description of ARgorithm. Helpful to people using your ARgorithm as well as other developers |
 
 You can check out ARgorithm examples in our Github Repo.
diff --git a/docs/docs/tutorials/bubblesort.md b/docs/docs/tutorials/bubblesort.md
index 57b80e0..00a02f4 100644
--- a/docs/docs/tutorials/bubblesort.md
+++ b/docs/docs/tutorials/bubblesort.md
@@ -53,22 +53,72 @@ The goal of ARgorithm is to create visualisations for educational purposes. Thus
 
 ## Setting up the config file
 
-Now that your argorithm is ready, it's time to configure the `bubblesort.config.json`.`argorithmID` and `file` is already filled and need not be altered. The `function` is set to `run` which is the function from the file we need to call. The `description` stored description of the agorithm. These are useful metadata for the CLI and server when it comes to parsing and execution. The most important keys are `parameters` and `default`.
+Now that your argorithm is ready, it's time to configure the `bubblesort.config.json`. We can use the configure command or create the file and set it up in code editor. Below we have demonstrated how to create the `bubblesort.config.json` using the `configure` command and how the file should look like. You can directly check out the final `bubblesort.config.json` below.
 
+<div class="termy">
+
+```console
+$ ARgorithm configure bubblesort 
+# Start CLI config generator?  [y/N]:$ y
+
++-----------------------------+
+|  ARGORITHM CONFIG GENERATOR |
++-----------------------------+
+
+ARgorithmID: bubblesort
+Codefile found: bubblesort.py
+# which function should be called [run]:$ run
+Enter ARgorithm Description
+Press ENTER on empty line to leave multiline input
+# :$ demonstrate bubble sort
+```
+
+</div>
+
+We need to define `array` which would be our array that we will sort
+
+<div class="termy">
 
+```console
+Setting up parameters for your argorithm
+input keywords are used to map the input passed to your function as kwargs
+
+The following input keywords were found in code
+- array
+input keyword: array
+# Enter parameter type:$ ARRAY
+# Enter type of array element:$ INT
+# Do you want to set a size constraint to array [y/N]:$ N
+Enter parameter description
+Press ENTER on empty line to leave multiline input:
+# :$ Array to be sorted
+
+# Do you want to another input keyword [y/N]:$ n
+```
 
-1. `parameters` : This key stores an object where each key is a key for the function `**kwargs` and its value is the type of value expected.
+</div>
 
-   
+We now need to define the default array that will be used when `array` is not input by user
 
-2. `default` : This key stores an object that specifies the default value for function `**kwargs`. These values would be used to in case of any exception in executing parameters. 
+<div class="termy">
 
-!!! info
-	The keys inside the parameters and default objects must be the same
+```console
+----------------------------------------
+ENTER INPUT FOR ARGORITHM
+----------------------------------------
+Based on argorithm parameters, input will be taken
 
+input keyword: array
+Description: Array to be sorted
+# Enter space separated series:$ 6 3 2 4 5 1
+
+```
+
+</div>
 
+This is how the `bubblesort.config.json` should look like.
 
-```JSON hl_lines="5-12"
+```JSON
 {!../../examples/bubblesort.config.json!}
 ```
 
diff --git a/docs/docs/tutorials/config.md b/docs/docs/tutorials/config.md
new file mode 100644
index 0000000..29aa875
--- /dev/null
+++ b/docs/docs/tutorials/config.md
@@ -0,0 +1,362 @@
+# Creating your configuration file
+
+The `.config.json` plays an important role in creating argorithms. It stores metadata and useful information that can be used to manage, run and customise input to argorithm. In this tutorial, we will be covering the .config.json step by step created using `configure` command. So lets get started. We'll be creating a `sample.config.json` for `sample.py`
+
+<div class="termy">
+
+```console
+$ ARgorithm init sample
+Creating empty template for sample
+[SUCCESS]: TEMPLATE GENERATED
+
+$ ARgorithm configure sample
+# Start CLI config generator?  [y/N]:$ y
+
++-----------------------------+
+|  ARGORITHM CONFIG GENERATOR |
++-----------------------------+
+
+```
+</div>
+
+## ARgorithm details
+
+as seen in the [Getting started](/toolkit/start), the configuration has the following properties
+
+| Key         | Description                                                  |
+| ----------- | ------------------------------------------------------------ |
+| argorithmID | name of your ARgorithm , this is generally pre filled from when you run the init command. The name of your code file should be *name*.py and the config should be *name*.config.json. [will be fixed later] |
+| file        | The file containing your codefile                            |
+| function    | The function that is going to be called                      |
+| parameters  | the parameters that your ARgorithm would need, this helps in anyone using your ARgorithm to understand what is the input format |
+| example     | default parameters in case no parameters are passed          |
+| description | The description of ARgorithm. Helpful to people using your ARgorithm as well as other developers |
+
+The `argorithmID` and `file` are read from the filename. The `sample.py` file is parsed by the CLI to list out eligible functions. an eligible function is one that can be called by ARgorithm. Your ARgorithm code file must have a function of the form `def foo(**kwargs)`. The input will be passed as keyword arguments according to metadata in config file. If you have more than one eligible function, you can decide which one to call.
+
+The `description` describe what the argorithm does so users know what the argorithm does and renders.
+
+<div class="termy">
+
+```console
+ARgorithmID: sample
+Codefile found: sample.py
+# which function should be called [run]:$ run
+Enter ARgorithm Description
+Press ENTER on empty line to leave multiline input
+# :$ sample config file to demonstrate config generator
+```
+
+</div>
+
+```json hl_lines="2-5"
+{!../../examples/sample.config.json!}
+```
+
+## Input parameters
+
+The `parameters` property is what defines the input to your argorithm. The properties defined inside `parameters` as passed in keyword arguments to your function. Inside the `parameters`, we define the type and input constraints and in `example`, we give a default value that can be used as input on that keyword.
+
+The CLI reads your code and shows you what iinput keywords your code looks for so that you can define its properties. you can add more parameters if you want but you will have to update your function to read that keyword argument.
+
+!!!info
+	Our current sample.py does not have any function code utilising keyword arguments. If your code does utilise some keyword arguments than you'll be asked to describe those particular input keywords.
+
+<div class="termy">
+
+```console
+Setting up parameters for your argorithm
+input keywords are used to map the input passed to your function as kwargs
+
+The following input keywords were found in code
+- array
+```
+
+</div>
+
+Each parameter has two neccessary fields: `type` and `description`.
+
+- `type`  : Decides the kind of input that is required to be taken from user. It can be of 5 types: `INT`,`FLOAT`,`STRING`,`ARRAY`,`MATRIX`. We'll cover creating parameters of each type below in detail.
+- `description` : Tells the user what this input parameter is for. This is useful in telling the user about the importance of this input and how it will be processed.
+
+### INT
+
+Parameters with `INT` type expect an integer input. You can add constraint to the range in which the integer input should be by using the `start` and `end` properties. Below is the schema of a parameter with type `INT`
+
+```json
+"properties" : {
+    "type" : {
+    	"const" : "INT"
+    },
+    "description" : {
+    	"type" : "string"
+    },
+    "start" : {
+    	"type" : "integer"
+    },
+    "end" : {
+    "type" : "integer"
+    }
+},
+"required" : ["type","description"]
+```
+
+<div class="termy">
+
+```console
+# Enter parameter name:$ n
+# Enter parameter type:$ INT
+# Do you want to add range constraints to n [y/N]:$ y
+# Enter lower limit:$ 0
+# Enter upper limit: $ 
+Enter parameter description
+Press ENTER on empty line to leave multiline input
+# :$ integer input
+```
+
+</div>
+
+In this example, we have created a input keyword `n` which requires a integer input larger than 0. Please note that the range specified by `start` and `end` is inclusive of the values
+
+$$
+n\in [start,end]
+$$
+
+```json hl_lines="7"
+{!../../examples/sample.config.json!}
+```
+
+### FLOAT
+
+Parameters with `FLOAT` type expect an numerical input which include both integers and floating point numbers. You can add constraint to the range in which the numerical input should be by using the `start` and `end` properties. Below is the schema of a parameter with type `FLOAT`
+
+```json
+"properties" : {
+    "type" : {
+    	"const" : "FLOAT"
+    },
+    "description" : {
+    	"type" : "string"
+    },
+    "start" : {
+    	"type" : "number"
+    },
+    "end" : {
+    	"type" : "number"
+    }
+},
+"required" : ["type","description"],
+```
+
+<div class="termy">
+
+```console
+# Enter parameter name:$ f
+# Enter parameter type:$ FLOAT
+# Do you want to add range constraints to f [y/N]:$ n
+Enter parameter description
+Press ENTER on empty line to leave multiline input
+# :$ floating point input
+```
+
+</div>
+
+In this example, we have defined input keyword `f` as a `float` which has no range constraints. Ranges in `FLOAT` works similar to `INT`.
+
+```json hl_lines="8"
+{!../../examples/sample.config.json!}
+```
+
+### STRING
+
+Parameters with type `STRING` take a single line string input from the user. This length of this string can be defined using the `size` property. `size` can store a integer value defining the size or can store the name of an `INT` type parameter so that size is input at runtime. `size` is an optional property, in case it is absent the user can enter a string of any length. Below is the schema of `STRING`
+
+```json
+"properties": {
+  "type": {
+    "const": "STRING"
+  },
+  "description": {
+    "type": "string"
+  },
+  "size": {
+    "type": ["integer", "string"]
+  }
+},
+  "required": ["type", "description"]
+```
+
+<div class="termy">
+
+```console
+# Enter parameter name:$ s
+# Enter parameter type:$ STRING
+# Do you want to set a size constraint to s [y/N]:$ y
+# Enter integer size or name of pre-existing INT type parameter:$ n
+Enter parameter description
+Press ENTER on empty line to leave multiline input
+# :$ string input
+```
+
+</div>
+
+Here we have defined `s` which is on type `string` and the length of string must be value stored in `n`.
+
+$$
+len(s) = n
+$$
+
+```json hl_lines="9"
+{!../../examples/sample.config.json!}
+```
+
+!!!warning
+	The input to `STRING` can be multiline but the input manager within CLI does not support that yet.
+
+### ARRAY
+
+Parameters with type `ARRAY` will expect a 1-dimensional series of items. The number of items in the series is controlled similarly to length of string i.e. using the `size` property. If `size` is not defined then the series can be of any size > 0. When using `ARRAY`, you need to define the `item-type` property as well. `item-type` can be `INT`,`FLOAT` or `STRING`. Below is the schema for `ARRAY` type parameters.
+
+```json
+"properties": {
+  "type": {
+    "const": "ARRAY"
+  },
+  "description": {
+    "type": "string"
+  },
+  "size": {
+    "type": ["integer", "string"]
+  },
+  "item-type": {
+    "type": "string",
+    "enum": ["INT", "FLOAT", "STRING"]
+  }
+},
+"required": ["type", "description", "item-type"]
+```
+
+<div class="termy">
+
+```console
+# Enter parameter name:$ arr
+# Enter parameter type:$ ARRAY
+# Enter type of array element:$ INT
+# Do you want to set a size constraint to arr [y/N]:$ n
+Enter parameter description
+Press ENTER on empty line to leave multiline input
+# :$ array input
+```
+
+Here we have defined `arr` of type `ARRAY` where each element has to be of type `INT`. The `size` of `arr` has not been defined so it can be of any size. 
+
+</div>
+
+```json hl_lines="10-14"
+{!../../examples/sample.config.json!}
+```
+
+### MATRIX
+
+Parameters with type `MATRIX` will expect a1-dimensional series of items. The dimensions are controlled by `row` and `column` which is parsed similar to the `size` property. Unlike `size`, `row` and `col` are neccessary properties.. When using `MATRIX`, you need to define the `item-type` property as well. `item-type` can be `INT`,`FLOAT` or `STRING`. Below is the schema for `MATRIX` type parameters.
+
+```json
+"properties": {
+  "type": {
+    "const": "ARRAY"
+  },
+  "description": {
+    "type": "string"
+  },
+  "row": {
+    "type": ["integer", "string"]
+  },
+  "col": {
+    "type": ["integer", "string"]
+  },
+  "item-type": {
+    "type": "string",
+    "enum": ["INT", "FLOAT", "STRING"]
+  }
+},
+  "required": ["type", "description", "col", "row", "item-type"],
+```
+
+<div class="termy">
+
+```console
+# Enter parameter name:$ mat 
+# Enter parameter type:$ MATRIX
+# Enter type of array element:$ INT
+# Enter integer row size or name of pre-existing INT type parameter:$ 4
+# Enter integer col_size or name of pre-existing INT type parameter:$ 3
+Enter parameter description
+Press ENTER on empty line to leave multiline input
+# :$ 2d input
+```
+
+</div>
+
+Here we have defined `mat` as a 4x3 matrix in which elements are type of `INT`.
+
+```json hl_lines="15-21"
+{!../../examples/sample.config.json!}
+```
+
+## Adding default values
+
+Now that we have defined our input parameters, we need to provide some default values to these in the `example` property.
+
+1. These values are used in case the user doesnt want to give custom input or gives faulty input to keywords
+2. These values are used for testing purposes as well
+
+The CLI generates input fields according to the parameters in which you can enter you details.
+
+<div class="termy">
+
+```console
+----------------------------------------
+ENTER INPUT FOR ARGORITHM
+----------------------------------------
+Based on argorithm parameters, input will be taken
+
+input keyword: n
+Description: integer input
+# Enter integer value:$ 6
+
+input keyword: f
+Description: floating point input
+# Enter integer value:$ 3.4
+
+input keyword: s
+Description: string input
+# Enter string value:$ sample
+
+input keyword: arr
+Description: array input
+# Enter space separated series:$ 3 4 1 2
+
+input keyword: mat
+Description: 2d input
+Enter matrix input, elements in each row must be space separated
+no. of rows: 4
+no. of elements per row: 3
+# :$ 1 4 2
+# :$ 5 4 2
+# :$ 5 6 4
+# :$ 8 1 9
+
+```
+
+</div>
+
+```json hl_lines="23-33"
+{!../../examples/sample.config.json!}
+```
+
+## Alternative methods
+
+You can generate a blank `sample.config.json` by using the `--config` option in the `init` command. You can then edit this file in your code editor.
+
+!!!info
+	We are working on GUI interface which should make the config generation process even more simpler
\ No newline at end of file
diff --git a/docs/docs/tutorials/fibonacci.md b/docs/docs/tutorials/fibonacci.md
index a00fe4e..8b7f6ee 100644
--- a/docs/docs/tutorials/fibonacci.md
+++ b/docs/docs/tutorials/fibonacci.md
@@ -39,7 +39,7 @@ $$
 
 ## Setting up the config file
 
-For this code, we only need one parameter that is `n` which is the index of the number required in the sequence. We will provide the default value for `n` as 4.
+For this code, we only need one parameter that is `n` which is the index of the number required in the sequence. We will provide the default value for `n` as 4. As shown in [previous tutorial](/toolkit/tutorials/bubblesort), you can create this using your code editor or the `configure` command [(how to use configure)](/toolkit/tutorials/config)
 ```json
 {!../../examples/fibonacci.config.json!}
 ```
diff --git a/docs/docs/tutorials/index.md b/docs/docs/tutorials/index.md
index 186e7f6..a4c1a6a 100644
--- a/docs/docs/tutorials/index.md
+++ b/docs/docs/tutorials/index.md
@@ -14,11 +14,11 @@ Creating empty template for hello_world
 refer documentation at https://argorithm.github.io/toolkit/ to learn how to use it
 chech out examples at https://github.com/ARgorithm/toolkit/tree/master/examples
 $ ls
-hello_world.config.json  hello_world.py
+hello_world.py
 ```
 </div>
 
-This creates the .config.json file and the .py file required to run the states. These files were covered in detail in the [getting started page](/toolkit/start). All the examples in this tutorials will be starting from this step onwards.
+This creates the template `.py` file  This file was covered once in the [getting started page](/toolkit/start). All the examples in this tutorials will be starting from this step onwards.
 
 ## Executing the code
 
diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml
index ff7098e..7a74561 100644
--- a/docs/mkdocs.yml
+++ b/docs/mkdocs.yml
@@ -28,12 +28,12 @@ nav:
 - Command Line Interface: cli.md
 - Tutorials:
   - Introduction: tutorials/index.md
+  - Configuration: tutorials/config.md
   - Bubblesort: tutorials/bubblesort.md
   - Fibonacci: tutorials/fibonacci.md
 - API Documentation: api/index.html
 - Releases: CHANGELOG.md
 - Need help?: help.md
-# - release-notes.md
 markdown_extensions:
 - mdx_math
 - toc:
diff --git a/examples/bubblesort.config.json b/examples/bubblesort.config.json
index 50e01ab..1fa158e 100644
--- a/examples/bubblesort.config.json
+++ b/examples/bubblesort.config.json
@@ -3,9 +3,13 @@
     "file": "bubblesort.py", 
     "function": "run", 
     "parameters": {
-        "array" : "list"
+        "array" : {
+            "description" : "Array to be sorted",
+            "type" : "ARRAY",
+            "item-type" : "INT"
+        }
     }, 
-    "default": {
+    "example": {
         "array" : [
             6,3,2,4,5,1
         ]
diff --git a/examples/bubblesort.py b/examples/bubblesort.py
index eb5eb76..5ea9a12 100644
--- a/examples/bubblesort.py
+++ b/examples/bubblesort.py
@@ -13,5 +13,3 @@ def run(**kwargs):
             if arr.compare(i,j,check,comments=f"comparing the {i}th and {j}th element"):
                 arr.swap(i,j,comments=f"as arr[{i}] > arr[{j}] , we swap them")
     return algo
-
-
diff --git a/examples/fibonacci.config.json b/examples/fibonacci.config.json
index 2b504b8..7a1b86a 100644
--- a/examples/fibonacci.config.json
+++ b/examples/fibonacci.config.json
@@ -3,9 +3,13 @@
     "file": "fibonacci.py", 
     "function": "run", 
     "parameters": {
-        "n" : "int"
+        "n" : {
+            "description" : "Enter the position of number in fibonacci series",
+            "type" : "INT",
+            "start" : 1
+        }
     }, 
-    "default": {
+    "example": {
         "n" : 4
     }, 
     "description": "Print the nth fibonacci number"
diff --git a/examples/sample.config.json b/examples/sample.config.json
new file mode 100644
index 0000000..af6a64d
--- /dev/null
+++ b/examples/sample.config.json
@@ -0,0 +1,36 @@
+{
+    "argorithmID": "sample",
+    "file": "sample.py",
+    "function": "run",
+    "description": "sample config to demonstrate config generation",
+    "parameters": {
+      "n": { "type": "INT", "start": 0, "description": "integer input" },
+      "f": { "type": "FLOAT", "description": "floating point input" },
+      "s": { "type": "STRING", "size": "n", "description": "string input" },
+      "arr": {
+        "type": "ARRAY",
+        "item-type": "INT",
+        "description": "array input"
+      },
+      "mat": {
+        "type": "MATRIX",
+        "item-type": "INT",
+        "row": 4,
+        "col": 3,
+        "description": "2d input"
+      }
+    },
+    "example": {
+      "n": 6,
+      "f": 3.4,
+      "s": "sample",
+      "arr": [3, 4, 1, 2],
+      "mat": [
+        [1, 4, 2],
+        [5, 4, 2],
+        [5, 6, 4],
+        [8, 1, 9]
+      ]
+    }
+  }
+  
\ No newline at end of file
diff --git a/examples/sample.py b/examples/sample.py
new file mode 100644
index 0000000..7f199e3
--- /dev/null
+++ b/examples/sample.py
@@ -0,0 +1,10 @@
+import ARgorithmToolkit
+
+def run(**kwargs):
+    algo = ARgorithmToolkit.StateSet()
+
+    #
+    # Your code
+    #
+
+    return algo
diff --git a/setup.py b/setup.py
index 70bec1c..d2eb03f 100644
--- a/setup.py
+++ b/setup.py
@@ -3,7 +3,7 @@
 with open("docs/README.md", "r") as fh:
     long_description = fh.read()
 
-__version__ = "0.1.1"
+__version__ = "0.2.0"
 
 setuptools.setup(
     name="ARgorithmToolkit",
@@ -20,11 +20,13 @@
         'Programming Language :: Python :: 3',
     ],
     python_requires='>=3.6',
+    include_package_data=True,
     install_requires=[
         'typer', # For CLI
         'requests' , #For CLI
         'numpy',
-        'halo'
+        'halo',
+        'jsonschema'
     ],
     project_urls={  # Optional
         'Source': 'https://github.com/ARgorithm/toolkit',


Test patch:
diff --git a/tests/test_encoder.py b/tests/test_encoder.py
new file mode 100644
index 0000000..5fbb345
--- /dev/null
+++ b/tests/test_encoder.py
@@ -0,0 +1,43 @@
+"""Testing JSON Encoder for ARgorithm containers
+"""
+import json
+import ARgorithmToolkit
+
+algo = ARgorithmToolkit.StateSet()
+arr = arr = ARgorithmToolkit.Array(name='arr',algo=algo,data=[1,2,3])
+dllnode = ARgorithmToolkit.DoublyLinkedListNode(algo,7)
+dll = ARgorithmToolkit.DoublyLinkedList("dllnode",algo)
+dl = ARgorithmToolkit.List("dl",algo)
+llnode = ARgorithmToolkit.LinkedListNode(algo,7)
+ll = ARgorithmToolkit.LinkedList("llnode",algo,llnode)
+fl = ARgorithmToolkit.ForwardList("fl",algo)
+pq = ARgorithmToolkit.PriorityQueue(name="pq",algo=algo)
+q = ARgorithmToolkit.Queue(name="q",algo=algo)
+st = ARgorithmToolkit.stack.Stack(name="st",algo=algo)
+s = ARgorithmToolkit.string.String(name="s",algo=algo,body="hello world")
+vec = ARgorithmToolkit.Vector(name='vec',algo=algo)
+
+def test_encoder():
+    """Tests serializability of all classes
+    """
+    objects = [
+        arr,dllnode,dll,dl,ll,llnode,fl,pq,q,s,vec,st
+    ]
+    json_string = json.dumps(objects,cls=ARgorithmToolkit.encoders.StateEncoder)
+    parsed_objects = json.loads(json_string)
+    for serialized,actual in zip(parsed_objects,objects):
+        modulename,classname_id = serialized.split('.')
+        try:
+            assert modulename == "$ARgorithmToolkit"
+            classname,obj_id = classname_id.split(':')
+            assert classname == actual.__class__.__name__
+            assert int(obj_id) == id(actual)
+        except AssertionError as ae:
+            if actual.__class__.__name__ == "Variable":
+                pass
+            raise Exception from ae
+        try:
+            json.dumps(algo,cls=ARgorithmToolkit.encoders.StateEncoder)
+            raise AssertionError("Should have raised type error")
+        except TypeError:
+            pass
diff --git a/tests/test_map.py b/tests/test_map.py
new file mode 100644
index 0000000..bdc51c7
--- /dev/null
+++ b/tests/test_map.py
@@ -0,0 +1,44 @@
+"""Test module for ARgorithmToolkit.Map"""
+import ARgorithmToolkit
+algo = ARgorithmToolkit.StateSet()
+str1 = ARgorithmToolkit.String("str1", algo, "xyz")
+map1 = ARgorithmToolkit.Map("map1", algo)
+def test_map():
+    """Tests Map body, states, and get/set methods
+    """
+    assert algo.states[-1].content['state_type'] == "map_declare"
+    map1["abcd"] = 123
+    map1.set(2,"hello")
+    map1[str1] = 456
+    assert algo.states[-1].content['state_type'] == "map_set"
+    assert map1[str1] == 456
+    assert map1["abcd"] == 123
+    assert map1[2] == "hello"
+    assert algo.states[-1].content['state_type'] == "map_get"
+    assert map1[str1] == 456
+    assert map1.get("123",-1) == -1
+    assert algo.states[-1].content['state_def']['value'] == -1
+
+def test_remove():
+    """Tests map item deletion
+    """
+    map1.remove("abcd")
+    assert algo.states[-1].content['state_type'] == "map_remove"
+    map1.remove("abcd")
+    assert algo.states[-1].content['state_def']['value'] == "none"
+    del map1[2]
+    assert algo.states[-1].content['state_type'] == "map_remove"
+    map1.get(2, "not found")
+    assert algo.states[-1].content['state_def']['value'] == "not found"
+    print(map1)
+
+def test_iteration():
+    """Tests map iteration
+    """
+    map1['123']=123
+    res = []
+    for key, value in map1:
+        res.append((key,value))
+
+    assert res == [(str1, 456),('123',123)]
+    assert algo.states[-1].content['state_type'] == "map_set"
diff --git a/tests/test_priorityqueue.py b/tests/test_priorityqueue.py
index 4ec0af0..38df984 100644
--- a/tests/test_priorityqueue.py
+++ b/tests/test_priorityqueue.py
@@ -56,5 +56,3 @@ def test_size():
     """Test priorityqueue size
     """
     assert queue.empty() and len(queue)==0
-
-
diff --git a/tests/test_queue.py b/tests/test_queue.py
index 5752330..82788e0 100644
--- a/tests/test_queue.py
+++ b/tests/test_queue.py
@@ -48,5 +48,3 @@ def test_size():
     """Test queue size
     """
     assert queue.empty() and len(queue)==0
-
-
diff --git a/tests/test_set.py b/tests/test_set.py
new file mode 100644
index 0000000..98ebca2
--- /dev/null
+++ b/tests/test_set.py
@@ -0,0 +1,85 @@
+"""Test module for ARgorithmToolkit.Set"""
+
+import ARgorithmToolkit
+from tests.utils import last_state
+
+algo = ARgorithmToolkit.StateSet()
+
+def test_init():
+    """test set declaration"""
+    l = [1,2,3]
+    t = (1,2,3)
+    vec = ARgorithmToolkit.Vector('vec',algo,[1,2,3])
+    arr = ARgorithmToolkit.Array('vec',algo,[1,2,3])
+
+    myset = ARgorithmToolkit.Set('myset',algo)
+    myset = ARgorithmToolkit.Set('myset',algo,l)
+    myset = ARgorithmToolkit.Set('myset',algo,t)
+    myset = ARgorithmToolkit.Set('myset',algo,arr)
+    myset = ARgorithmToolkit.Set('myset',algo,vec)
+
+    state = last_state(algo)
+    assert state['state_type'] == "set_declare"
+    assert myset.body == set([1,2,3])
+
+def test_add_remove_find():
+    """test internal set operations such as add,find,remove"""
+    myset = ARgorithmToolkit.Set('myset',algo)
+    myset.add(3)
+    myset.add(3)
+    myset.add(3.14)
+    myset.add('abc')
+    myset.add(True)
+
+    assert myset.body == set([3,3.14,'abc',True])
+
+    st = ARgorithmToolkit.String("mystr",algo,"hello")
+    myset.add(st,"adding an ARgorithmToolkit.String")
+    try:
+        myset.add(algo)
+        assert False
+    except TypeError:
+        pass
+
+    state = last_state(algo)
+    assert state['state_type'] == "set_add"
+    assert state['comments'] == "adding an ARgorithmToolkit.String"
+
+    myset.remove(3,comments="remove 3")
+    myset.remove(st,comments="remove ARgorithmToolkit.String object")
+    try:
+        myset.remove(4)
+        assert False
+    except ARgorithmToolkit.ARgorithmError:
+        pass
+
+    assert myset.body == set([3.14,'abc',True])
+
+    state = last_state(algo)
+    assert state['state_type'] == "set_remove"
+    assert state['comments'] == "remove ARgorithmToolkit.String object"
+
+    assert myset.find(3.14)
+    assert not myset.find(3)
+
+    state = last_state(algo)
+    assert state['state_type'] == "set_find"
+
+def test_union_intersection_difference():
+    """test operations between sets"""
+    set1 = ARgorithmToolkit.Set('set1',algo,[1,2,3])
+    set2 = ARgorithmToolkit.Set('set1',algo,[2,4,5])
+
+    union_set = set1.union(set2)
+    diff_set = set1.difference(set2)
+    inter_set = set1.intersection(set2)
+    assert union_set.body == set([1,2,3,4,5])
+    assert diff_set.body == set([1,3])
+    assert inter_set.body == set([2])
+
+    state = last_state(algo)
+    assert state["state_type"] == "set_declare"
+    state = last_state(algo)
+    assert state["state_type"] == "set_declare"
+    state = last_state(algo)
+    assert state["state_type"] == "set_declare"
diff --git a/tests/test_stack.py b/tests/test_stack.py
index 4078194..189f942 100644
--- a/tests/test_stack.py
+++ b/tests/test_stack.py
@@ -42,5 +42,3 @@ def test_size():
     """Test size operations
     """
     assert stack.empty() and len(stack)==0
-
-
diff --git a/tests/test_string.py b/tests/test_string.py
index 44d4b4c..064bf95 100644
--- a/tests/test_string.py
+++ b/tests/test_string.py
@@ -56,6 +56,3 @@ def test_iteration():
         last_state = algo.states[-1]
         assert last_state.content["state_type"] == 'string_iter'
         assert last_state.content["state_def"]["index"] == i
-
-
-
diff --git a/tests/test_vector.py b/tests/test_vector.py
index 1ee1086..5395788 100644
--- a/tests/test_vector.py
+++ b/tests/test_vector.py
@@ -106,4 +106,3 @@ def test_swap():
     assert last_state.content["state_def"]["index1"] == 0
     assert last_state.content["state_def"]["index2"] == 1
     assert last_state.content["state_def"]["body"] == arr.body
-