Uniform Cost Search for Graph

in #algorithm7 years ago (edited)

Requirements:
BFS
DFS

Uniform Cost Search is the best algorithm for a search problem, which does not involve the use of heuristic function. UCS finds the optimal path between the two nodes in directed or undirected graph. When all step costs are equal, breadth-first search is optimal because it always expands the shallowest unexpanded node. By a simple extension, we can find an algorithm that is optimal with any step-cost function. Instead of expanding the shallowest node, uniform-cost search expands the node n with the lowest path cost g(n). This is done by storing the frontier as a priority queue ordered by g(n).

Heuristic function is estimated cost of the cheapest path from the 
state at node n to a goal state which is known at the beginning.
Heuristic function are only given for a search algorithms which 
come under informed search while UCS is uninformed search.

Frontier is the set of all leaf nodes available for expansion at a
given point here which is stored as a priority queue with highest 
priority for node with smallest cost path. 

ref:: Artificial Intelligence: A Modern Approach 
       by S.Russell and P.Norvig


Uses/Application of UCS:
Imagine You have map of state with distance mentioned between all adjacent cities now you want to travel from city 1 to city 8 but you have several different combination of routes to select. In such cases UCS can be used to select an optimal path. By considering cities as individual nodes and distance as cost of traversal between two nodes.

Lets take the directed graph given below as example:
graph_path_cost-1.png

These are all the possible paths to reach from node 0 to node 7 with the cost of traversal
path: 0->1->3->5->4->6->7 cost: 12
path: 0->2->5->4->6->7 cost: 9
path: 0->2->5->8->4->7 cost: 10
path: 0->1->3->5->8->9->7 cost: 11
path: 0->2->5->8->9->7 cost: 8
path: 0->1->3->5->4->7 cost: 15
path: 0->1->3->6->7 cost: 9
path: 0->2->5->4->7 cost: 12
path: 0->1->3->5->8->4->7 cost: 13
path: 0->2->5->8->4->6->7 cost: 7
path: 0->1->3->5->8->4->6->7 cost: 10

best path: 0->2->5->8->4->6->7

Python Code:

import copy
import Queue as Q

class Graph:

# graph dictonary contains all the adjacent nodes of each as key and value pair
# cost_dict contains cost of each edge traversal of (u,v)
# final_dict contains all the possible paths from start node s to goal node g with total cost
def __init__(self):
    self.graph = dict()
    self.cost_dict=dict()
    self.final_dict=dict()

# u and v are nodes: edge u-->v with cost c 
def addEdge(self,u,v,c):
    
    if u not in self.graph:
        qu = Q.PriorityQueue()
        self.graph.update({u:qu})

    self.graph[u].put(v)
    self.cost_dict.update({(u,v):c})
    
# Makes a list to keep track of visited nodes
def tnode(self,n):
    self.visited = [False]*n


def UCS_util(self,s,visited,path,goal,value):
    # Appending node to the current path 
    path.append(s)
    # Marking that node is visited 
    visited[s]=True
    
    # If goal node is reached save the path and return
    if goal==s:
        self.final_dict.update({tuple(path):value})
        return
    
    # Checking if the adjacent node is been visited and explore the new path if haven't
    for i in self.graph[s].queue:
        if visited[i]==False:
            # When new path is being explored add the cost of that path to cost of entire course traversal
            # Send a copy of path list to avoid sending it by reference
            self.UCS_util(i,copy.deepcopy(visited),copy.deepcopy(path),goal,value + self.cost_dict[s,i])

def UCS(self, s,goal):
    self.visited[s] = True
    # List to hold all the nodes visited in path from start node to goal node 
    path=[s]
    
    for i in self.graph[s].queue:
        if self.visited[i] == False:
            # Make a variable to hold the cost of traversal
            value = self.cost_dict[s,i]
            self.UCS_util(i,copy.deepcopy(self.visited),copy.deepcopy(path),goal,value)

# Display all the paths that is been discovered from start node to Goal node
def all_paths(self):
    # Check if there is any path
    if bool(self.final_dict):
        print("All the paths: ")
        for i in self.final_dict:
            print "path: ",i,"cost: ",self.final_dict[i]
    else:
        print "No Path exist between start and goal node"

# Find the most optimal path between start node to goal node
def optimal_path(self):
    if bool(self.final_dict):
        print "best path: ",min(self.final_dict, key=self.final_dict.get)
    else:
        print "No Path exist between start and goal node"

Creating Graph object and assigning number of nodes

g = Graph()
g.tnode(10)

Making the Graph

g.addEdge(0, 1, 1); g.addEdge(0, 2, 1); g.addEdge(1, 3, 3);
g.addEdge(2, 5, 2); g.addEdge(3, 6, 4); g.addEdge(3, 5, 2);
g.addEdge(4, 6, 1); g.addEdge(4, 7, 5); g.addEdge(5, 4, 4);
g.addEdge(6, 7, 1); g.addEdge(5, 0, 3); g.addEdge(5, 8, 1);
g.addEdge(8, 4, 1); g.addEdge(8, 9, 3); g.addEdge(9, 7, 1);

0 is start node and 7 is goal node

g.UCS(0,7)

Find all the path between 0 and 7

g.all_paths()

Find the most optimal path between 0 and 7

g.optimal_path()

Output:

All the paths:
path: (0, 1, 3, 5, 4, 6, 7) cost: 12
path: (0, 2, 5, 4, 6, 7) cost: 9
path: (0, 2, 5, 8, 4, 7) cost: 10
path: (0, 1, 3, 5, 8, 9, 7) cost: 11
path: (0, 2, 5, 8, 9, 7) cost: 8
path: (0, 1, 3, 5, 4, 7) cost: 15
path: (0, 1, 3, 6, 7) cost: 9
path: (0, 2, 5, 4, 7) cost: 12
path: (0, 1, 3, 5, 8, 4, 7) cost: 13
path: (0, 2, 5, 8, 4, 6, 7) cost: 7
path: (0, 1, 3, 5, 8, 4, 6, 7) cost: 10


best path: (0, 2, 5, 8, 4, 6, 7)
































Sort:  

Congratulations @vamshikshetty! You have completed some achievement on Steemit and have been rewarded with new badge(s) :

Award for the number of upvotes

Click on any badge to view your own Board of Honor on SteemitBoard.
For more information about SteemitBoard, click here

If you no longer want to receive notifications, reply to this comment with the word STOP

By upvoting this notification, you can help all Steemit users. Learn how here!

Congratulations @vamshikshetty! You have received a personal award!

1 Year on Steemit
Click on the badge to view your Board of Honor.

Do not miss the last post from @steemitboard:

SteemitBoard Ranking update - Resteem and Resteemed added

Support SteemitBoard's project! Vote for its witness and get one more award!

Congratulations @vamshikshetty! You received a personal award!

Happy Birthday! - You are on the Steem blockchain for 2 years!

You can view your badges on your Steem Board and compare to others on the Steem Ranking

Vote for @Steemitboard as a witness to get one more award and increased upvotes!

Coin Marketplace

STEEM 0.17
TRX 0.16
JST 0.029
BTC 75813.73
ETH 2916.82
USDT 1.00
SBD 2.62