Uniform-Cost Search (Dijkstra for large Graphs)
Uniform-Cost Search is a variant of Dijikstra’s algorithm. Here, instead of inserting all vertices into a priority queue, we insert only the source, then one by one insert when needed. In every step, we check if the item is already in the priority queue (using the visited array). If yes, we perform the decrease key, else we insert it.
This variant of Dijkstra is useful for infinite graphs and that graph which are too large to represent in memory. Uniform-Cost Search is mainly used in Artificial Intelligence.
Examples:
Input :
Output : Minimum cost from S to G is =3
Uniform-Cost Search is similar to Dijikstra’s algorithm. In this algorithm from the starting state, we will visit the adjacent states and will choose the least costly state then we will choose the next least costly state from the all un-visited and adjacent states of the visited states, in this way we will try to reach the goal state (note we won’t continue the path through a goal state ), even if we reach the goal state we will continue searching for other possible paths( if there are multiple goals). We will keep a priority queue that will give the least costly next state from all the adjacent states of visited states.
C++
// C++ implementation of above approach #include <bits/stdc++.h> using namespace std; // graph vector<vector< int > > graph; // map to store cost of edges map<pair< int , int >, int > cost; // returns the minimum cost in a vector( if // there are multiple goal states) vector< int > uniform_cost_search(vector< int > goal, int start) { // minimum cost upto // goal state from starting // state vector< int > answer; // create a priority queue priority_queue<pair< int , int > > queue; // set the answer vector to max value for ( int i = 0; i < goal.size(); i++) answer.push_back(INT_MAX); // insert the starting index queue.push(make_pair(0, start)); // map to store visited node map< int , int > visited; // count int count = 0; // while the queue is not empty while (queue.size() > 0) { // get the top element of the // priority queue pair< int , int > p = queue.top(); // pop the element queue.pop(); // get the original value p.first *= -1; // check if the element is part of // the goal list if (find(goal.begin(), goal.end(), p.second) != goal.end()) { // get the position int index = find(goal.begin(), goal.end(), p.second) - goal.begin(); // if a new goal is reached if (answer[index] == INT_MAX) count++; // if the cost is less if (answer[index] > p.first) answer[index] = p.first; // pop the element queue.pop(); // if all goals are reached if (count == goal.size()) return answer; } // check for the non visited nodes // which are adjacent to present node if (visited[p.second] == 0) for ( int i = 0; i < graph[p.second].size(); i++) { // value is multiplied by -1 so that // least priority is at the top queue.push(make_pair((p.first + cost[make_pair(p.second, graph[p.second][i])]) * -1, graph[p.second][i])); } // mark as visited visited[p.second] = 1; } return answer; } // main function int main() { // create the graph graph.resize(7); // add edge graph[0].push_back(1); graph[0].push_back(3); graph[3].push_back(1); graph[3].push_back(6); graph[3].push_back(4); graph[1].push_back(6); graph[4].push_back(2); graph[4].push_back(5); graph[2].push_back(1); graph[5].push_back(2); graph[5].push_back(6); graph[6].push_back(4); // add the cost cost[make_pair(0, 1)] = 2; cost[make_pair(0, 3)] = 5; cost[make_pair(1, 6)] = 1; cost[make_pair(3, 1)] = 5; cost[make_pair(3, 6)] = 6; cost[make_pair(3, 4)] = 2; cost[make_pair(2, 1)] = 4; cost[make_pair(4, 2)] = 4; cost[make_pair(4, 5)] = 3; cost[make_pair(5, 2)] = 6; cost[make_pair(5, 6)] = 3; cost[make_pair(6, 4)] = 7; // goal state vector< int > goal; // set the goal // there can be multiple goal states goal.push_back(6); // get the answer vector< int > answer = uniform_cost_search(goal, 0); // print the answer cout << "Minimum cost from 0 to 6 is = " << answer[0] << endl; return 0; } |
Java
// Java implementation of above approach import java.util.*; public class GFG { // graph static List<List<Integer>> graph = new ArrayList<List<Integer>>(); // map to store cost of edges static HashMap<List<Integer>, Integer> cost = new HashMap<List<Integer>, Integer>(); // returns the minimum cost in a vector( if // there are multiple goal states) static List<Integer> uniform_cost_search(List<Integer> goal, int start) { // minimum cost upto // goal state from starting // state List<Integer> answer = new ArrayList<Integer>(); // create a priority queue List<Tuple<Integer, Integer>> queue = new ArrayList<Tuple<Integer, Integer>>(); // set the answer vector to max value for ( int i = 0 ; i < goal.size(); i++) answer.add(Integer.MAX_VALUE); // insert the starting index queue.add( new Tuple<Integer, Integer>( 0 , start)); // map to store visited node HashMap<Integer, Integer> visited = new HashMap<Integer, Integer>(); // count int count = 0 ; // while the queue is not empty while (!queue.isEmpty()) { // get the top element of the // priority queue Tuple<Integer, Integer> q = queue.get( 0 ); Tuple<Integer, Integer> p = new Tuple<Integer, Integer>(-q.x, q.y); // pop the element queue.remove( 0 ); if (goal.contains(p.y)) { // get the position int index = goal.indexOf(p.y); // if a new goal is reached if (answer.get(index) == Integer.MAX_VALUE) count++; // if the cost is less if (answer.get(index) > p.x) answer.set(index, p.x); // pop the element queue.remove( 0 ); // if all goals are reached if (count == goal.size()) return answer; } if (!visited.containsKey(p.y)) for ( int i = 0 ; i < graph.get(p.y).size(); i++) { // value is multiplied by -1 so that // least priority is at the top queue.add( new Tuple<Integer, Integer>((p.x + (cost.containsKey(Arrays.asList(p.y, graph.get(p.y).get(i))) ? cost.get(Arrays.asList(p.y, graph.get(p.y).get(i))) : 0 )) * - 1 , graph.get(p.y).get(i))); } // mark as visited visited.put(p.y, 1 ); } return answer; } // main function public static void main(String[] args) { // create the graph graph = new ArrayList<List<Integer>>(); for ( int i = 0 ; i < 7 ; i++) { graph.add( new ArrayList<Integer>()); } // add edges graph.get( 0 ).add( 1 ); graph.get( 0 ).add( 3 ); graph.get( 3 ).add( 1 ); graph.get( 3 ).add( 6 ); graph.get( 3 ).add( 4 ); graph.get( 1 ).add( 6 ); graph.get( 4 ).add( 2 ); graph.get( 4 ).add( 5 ); graph.get( 2 ).add( 1 ); graph.get( 5 ).add( 2 ); graph.get( 5 ).add( 6 ); graph.get( 6 ).add( 4 ); // add the cost cost.put(Arrays.asList( 0 , 1 ), 2 ); cost.put(Arrays.asList( 0 , 3 ), 5 ); cost.put(Arrays.asList( 1 , 6 ), 1 ); cost.put(Arrays.asList( 3 , 1 ), 5 ); cost.put(Arrays.asList( 3 , 6 ), 6 ); cost.put(Arrays.asList( 3 , 4 ), 2 ); cost.put(Arrays.asList( 2 , 1 ), 4 ); cost.put(Arrays.asList( 4 , 2 ), 4 ); cost.put(Arrays.asList( 4 , 5 ), 3 ); cost.put(Arrays.asList( 5 , 2 ), 6 ); cost.put(Arrays.asList( 5 , 6 ), 3 ); cost.put(Arrays.asList( 6 , 4 ), 7 ); // goal state List<Integer> goal = new ArrayList<Integer>(); goal.add( 6 ); List<Integer> answer = uniform_cost_search(goal, 0 ); // print the answer System.out.print( "Minimum cost from 0 to 6 is = " + answer.get( 0 )); } } class Tuple<X, Y> { public final X x; public final Y y; public Tuple(X x, Y y) { this .x = x; this .y = y; } } |
Python3
# Python3 implementation of above approach # returns the minimum cost in a vector( if # there are multiple goal states) def uniform_cost_search(goal, start): # minimum cost upto # goal state from starting global graph,cost answer = [] # create a priority queue queue = [] # set the answer vector to max value for i in range ( len (goal)): answer.append( 10 * * 8 ) # insert the starting index queue.append([ 0 , start]) # map to store visited node visited = {} # count count = 0 # while the queue is not empty while ( len (queue) > 0 ): # get the top element of the queue = sorted (queue) p = queue[ - 1 ] # pop the element del queue[ - 1 ] # get the original value p[ 0 ] * = - 1 # check if the element is part of # the goal list if (p[ 1 ] in goal): # get the position index = goal.index(p[ 1 ]) # if a new goal is reached if (answer[index] = = 10 * * 8 ): count + = 1 # if the cost is less if (answer[index] > p[ 0 ]): answer[index] = p[ 0 ] # pop the element del queue[ - 1 ] queue = sorted (queue) if (count = = len (goal)): return answer # check for the non visited nodes # which are adjacent to present node if (p[ 1 ] not in visited): for i in range ( len (graph[p[ 1 ]])): # value is multiplied by -1 so that # least priority is at the top queue.append( [(p[ 0 ] + cost[(p[ 1 ], graph[p[ 1 ]][i])]) * - 1 , graph[p[ 1 ]][i]]) # mark as visited visited[p[ 1 ]] = 1 return answer # main function if __name__ = = '__main__' : # create the graph graph,cost = [[] for i in range ( 8 )],{} # add edge graph[ 0 ].append( 1 ) graph[ 0 ].append( 3 ) graph[ 3 ].append( 1 ) graph[ 3 ].append( 6 ) graph[ 3 ].append( 4 ) graph[ 1 ].append( 6 ) graph[ 4 ].append( 2 ) graph[ 4 ].append( 5 ) graph[ 2 ].append( 1 ) graph[ 5 ].append( 2 ) graph[ 5 ].append( 6 ) graph[ 6 ].append( 4 ) # add the cost cost[( 0 , 1 )] = 2 cost[( 0 , 3 )] = 5 cost[( 1 , 6 )] = 1 cost[( 3 , 1 )] = 5 cost[( 3 , 6 )] = 6 cost[( 3 , 4 )] = 2 cost[( 2 , 1 )] = 4 cost[( 4 , 2 )] = 4 cost[( 4 , 5 )] = 3 cost[( 5 , 2 )] = 6 cost[( 5 , 6 )] = 3 cost[( 6 , 4 )] = 7 # goal state goal = [] # set the goal # there can be multiple goal states goal.append( 6 ) # get the answer answer = uniform_cost_search(goal, 0 ) # print the answer print ( "Minimum cost from 0 to 6 is = " ,answer[ 0 ]) # This code is contributed by mohit kumar 29 |
C#
// C# implementation of above approach using System; using System.Collections; using System.Collections.Generic; class GFG { // graph static List<List< int >> graph= new List<List< int >>(); // map to store cost of edges static Dictionary<Tuple< int , int >, int > cost= new Dictionary<Tuple< int , int >, int >(); // returns the minimum cost in a vector( if // there are multiple goal states) static List< int > uniform_cost_search(List< int > goal, int start) { // minimum cost upto // goal state from starting // state List< int > answer= new List< int >(); // create a priority queue List<Tuple< int , int > > queue = new List<Tuple< int , int > >(); // set the answer vector to max value for ( int i = 0; i < goal.Count; i++) answer.Add( int .MaxValue); // insert the starting index queue.Add( new Tuple< int , int >(0, start)); // map to store visited node Dictionary< int , int > visited= new Dictionary< int , int >(); // count int count = 0; // while the queue is not empty while (queue.Count > 0) { // get the top element of the // priority queue Tuple< int , int > q = queue[0]; Tuple< int , int > p = new Tuple< int , int >(-q.Item1,q.Item2); // pop the element queue.RemoveAt(0); // check if the element is part of // the goal list if (goal.Contains(p.Item2)) { // get the position int index = goal.IndexOf(p.Item2); // if a new goal is reached if (answer[index] == int .MaxValue) count++; // if the cost is less if (answer[index] > p.Item1) answer[index] = p.Item1; // pop the element queue.RemoveAt(0); // if all goals are reached if (count == goal.Count) return answer; } // check for the non visited nodes // which are adjacent to present node if (!visited.ContainsKey(p.Item2)) for ( int i = 0; i < graph[p.Item2].Count; i++) { // value is multiplied by -1 so that // least priority is at the top queue.Add( new Tuple< int , int >((p.Item1 + (cost.ContainsKey( new Tuple< int , int >(p.Item2, graph[p.Item2][i])) ? cost[ new Tuple< int , int >(p.Item2, graph[p.Item2][i])] : 0))*-1, graph[p.Item2][i])); } // mark as visited visited[p.Item2] = 1; } return answer; } // main function public static void Main( params string []args) { // create the graph graph= new List<List< int >>(); for ( int i=0;i<7;i++) { graph.Add( new List< int >()); } // add edge graph[0].Add(1); graph[0].Add(3); graph[3].Add(1); graph[3].Add(6); graph[3].Add(4); graph[1].Add(6); graph[4].Add(2); graph[4].Add(5); graph[2].Add(1); graph[5].Add(2); graph[5].Add(6); graph[6].Add(4); // add the cost cost[ new Tuple< int , int >(0, 1)] = 2; cost[ new Tuple< int , int >(0, 3)] = 5; cost[ new Tuple< int , int >(1, 6)] = 1; cost[ new Tuple< int , int >(3, 1)] = 5; cost[ new Tuple< int , int >(3, 6)] = 6; cost[ new Tuple< int , int >(3, 4)] = 2; cost[ new Tuple< int , int >(2, 1)] = 4; cost[ new Tuple< int , int >(4, 2)] = 4; cost[ new Tuple< int , int >(4, 5)] = 3; cost[ new Tuple< int , int >(5, 2)] = 6; cost[ new Tuple< int , int >(5, 6)] = 3; cost[ new Tuple< int , int >(6, 4)] = 7; // goal state List< int > goal= new List< int >(); // set the goal // there can be multiple goal states goal.Add(6); // get the answer List< int > answer = uniform_cost_search(goal, 0); // print the answer Console.Write( "Minimum cost from 0 to 6 is = " + answer[0]); } } // This code is contributed by rutvik_56. |
Javascript
// returns the minimum cost in a vector( if // there are multiple goal states) function uniform_cost_search(goal, start) { // minimum cost upto // goal state from starting let answer = []; // create a priority queue let queue = []; // set the answer vector to max value for (let i = 0; i < goal.length; i++) { answer.push(10 ** 8); } // insert the starting index queue.push([0, start]); // map to store visited node let visited = {}; // count let count = 0; // while the queue is not empty while (queue.length > 0) { // get the top element of the queue.sort(); let p = queue[queue.length - 1]; // pop the element queue.splice(queue.length - 1, 1); // get the original value p[0] *= -1; // check if the element is part of // the goal list if (goal.includes(p[1])) { // get the position let index = goal.indexOf(p[1]); // if a new goal is reached if (answer[index] === 10 ** 8) { count += 1; } // if the cost is less if (answer[index] > p[0]) { answer[index] = p[0]; } // pop the element queue.splice(queue.length - 1, 1); queue.sort(); if (count === goal.length) { return answer; } } // check for the non visited nodes // which are adjacent to present node if (!visited[p[1]]) { for (let i = 0; i < graph[p[1]].length; i++) { // value is multiplied by -1 so that // least priority is at the top queue.push([ (p[0] + cost[p[1] + "," + graph[p[1]][i]]) * -1, graph[p[1]][i], ]); } } // mark as visited visited[p[1]] = true ; } return answer; } // create the graph let graph = [[], [], [], [], [], [], [], []]; let cost = {}; // add edge graph[0].push(1); graph[0].push(3); graph[3].push(1); graph[3].push(6); graph[3].push(4); graph[1].push(6); graph[4].push(2); graph[4].push(5); graph[2].push(1); graph[5].push(2); graph[5].push(6); graph[6].push(4); // add the cost cost[ "0,1" ] = 2; cost[ "0,3" ] = 5; cost[ "1,6" ] = 1; cost[ "3,1" ] = 5; cost[ "3,6" ] = 6; cost[ "3,4" ] = 2; cost[ "2,1" ] = 4; cost[ "4,2" ] = 4; cost[ "4,5" ] = 3; cost[ "5,2" ] = 6; cost[ "5,6" ] = 3; cost[ "6,4" ] = 7; // goal state goal = [] // set the goal // there can be multiple goal states goal.push(6) // get the answer answer = uniform_cost_search(goal, 0) // print the answer console.log( "Minimum cost from 0 to 6 is = " ,answer[0]) // This code is contributed by lokeshpotta20. |
Minimum cost from 0 to 6 is = 3
Time Complexity: O( m ^ (1+floor(l/e)))
where,
m is the maximum number of neighbors a node has
l is the length of the shortest path to the goal state
e is the least cost of an edge
Please Login to comment...