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++ 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 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 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# 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. |
// 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