So I have been working on a Breadth First Search to get a path given a starting and ending node. However in some cases it seems to fail and not get the path, which I know is possible since a Depth First Search and visual inspection shows that it should exist.
I have an Adjacency Matrix:
1 2 3 4 5 6 7 8
1 0 20 25 20 0 0 0 0
2 20 0 5 0 30 0 0 0
3 25 5 0 13 8 21 0 0
4 20 0 13 0 0 17 0 0
5 0 30 8 0 0 33 0 0
6 0 0 21 17 33 0 0 0
7 0 0 0 0 0 0 0 10
8 0 0 0 0 0 0 10 0
Which has a graph as follows:
This is my function:
void Network::BFS(int src, int dest, vector<bool>& visited, vector<int>& path) {
// The Queue is the core for the BFS.
queue<int> Queue;
// Mark current node as visited.
visited[src] = true;
Queue.push(src);
// While queue is not empty.
while (!Queue.empty()) {
// Add node to path.
// Check if we have found the destination yet or not, if we have we do one last push to path and we're done!
if (Queue.front() == dest) {
return;
}
int top = Queue.front();
path.push_back(Queue.front());
// Pop off front.
Queue.pop();
// Iterate and process all none visited nodes.
for (int node = 0; node < amountOfNodes; node++) {
// Check if it is not visited already.
if (visited[node] == false && (adjMatrix[node * amountOfNodes + src] != 0)) {
Queue.push(node); // Add to end.
visited[node] = true;
}
}
}
}
Sample input and output:
(6, 3) -> Path is: 6
(1, 5) -> Path is: 1 2 3 4
As you can see, it does not compute the path properly at all. Where is my algorithm going wrong here, and how do I fix it?
BFS involves visiting adjacent nodes in a FIFO fashion. Once you reach a node, you put into the queue all its neighbours, unless they were already visited.
First off, there's a typo where you iterate over adjacent nodes. You want to traverse the top column, not the src one:
adjMatrix[node * amountOfNodes + top] != 0
// ~~^
Secondly, your current path implementation stores the visit order of nodes, not a path from the source to its destination. For the latter, you need to store the parent of each node, so that the final path can be restored by going from a child (destination) to its parent, grandparent, great-grandparent, ..., etc.
std::vector<int> parent(amountOfNodes, -1);
//...
if (visited[node] == false && (adjMatrix[node * amountOfNodes + top] != 0))
{
Queue.push(node); // Add to end.
visited[node] = true;
parent[node] = top;
}
Restoring the path is straightforward:
int u = dest;
do
{
std::cout << u << " ";
u = parent[u];
}
while (u != -1);
DEMO
Related
I have been give a problem in which I am provided with user-entered matrix (rows and columns). User will also provide Start State (row and column) and the Goal State.
The job is to use A* search to find the path from the start node to the goal node.
A sample matrix is provided below,
0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 0 0 0 0 G
0 0 0 1 1 0 0 0 1 1
0 0 0 0 0 0 0 0 0 0
0 1 1 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 1 1 0 0 0
0 0 0 0 0 1 1 0 0 0
0 1 0 1 0 1 1 0 0 0
0 1 0 1 0 1 1 0 0 0
0 0 0 0 0 0 0 0 0 0
S 0 0 0 0 0 0 0 0 0
0 1 0 0 0 1 1 0 0 0
0 0 0 0 0 1 1 0 0 0
where "S" is the start state, and "G" is the goal state. 0 are the states, in which you can move to and 1 are the obstacles in the grid, you can't move to them.
There are 3 actions allowed.
Up one cell (cost is 1)
right one cell (cost is 3)
diagonally up towards the right (cost is 2)
To solve this problem, I used Manhattan's Distance as my heuristic function and calculated the heuristic values for all my states.... They looked something like this (for the grid specified above)
10 9 8 7 6 5 4 3 2 1
9 8 7 6 5 4 3 2 1 0
10 9 8 7 6 5 4 3 2 1
11 10 9 8 7 6 5 4 3 2
12 11 10 9 8 7 6 5 4 3
13 12 11 10 9 8 7 6 5 4
14 13 12 11 10 9 8 7 6 5
15 14 13 12 11 10 9 8 7 6
16 15 14 13 12 11 10 9 8 7
17 16 15 14 13 12 11 10 9 8
18 17 16 15 14 13 12 11 10 9
19 18 17 16 15 14 13 12 11 10
20 19 18 17 16 15 14 13 12 11
21 20 19 18 17 16 15 14 13 12
Now, this is my code for A* search
void A_search()
{
priority_queue<node, vector<node>, CompareCost>q; // Priority Queue is used.
// node contains 4 elements... 1. "Heuristic" value, 2. Index row, 3. Index Col, 4. Actual Cost until this point
q.push(node(heuristic[srow][scol], srow, scol, 0)); // srow, scol is start state. 0 is Actual Cost
while (!q.empty())
{
node temp = q.top();
path_cost = temp.cost; // path_cost is global variable, which stores actual cost until this point
path[temp.i][temp.j] = true; // Boolean array, which tells the path followed so far.
q.pop();
if (temp.i == grow && temp.j == gcol) // If goal state is found, we break out of the loop
break;
if (temp.i > 0) // Checking for rows above the current state.
{
if (arr[temp.i - 1][temp.j] != 1) // Checking if index above current state is obstacle or not
{
q.push(node(heuristic[temp.i - 1][temp.j] + (temp.cost+1), temp.i - 1, temp.j, temp.cost + 1)); // pushing the above index into queue
}
if (temp.j - 1 < cols)
{
if (arr[temp.i - 1][temp.j + 1] != 1) // Diagonal Index checking
{
q.push(node(heuristic[temp.i - 1][temp.j + 1] + (temp.cost + 2), temp.i - 1, temp.j + 1, temp.cost + 2));
}
}
}
if (temp.j - 1 < cols) // Horizontal Index... Checking if column has exceeded the total cols or not
{
if (arr[temp.i][temp.j + 1] != 1) // Obstacle check for horizontal index
{
q.push(node(heuristic[temp.i][temp.j + 1] + (temp.cost + 3), temp.i, temp.j + 1, temp.cost + 3));
}
}
}
}
And this is the result I get after running this algorithm (Please note that # represents the path taken by the program... I am simply using a boolean 2D array to check which nodes are being visited by Priority Queue. For those indexes only, I am printing # and rest of the grid remains the same)
0 0 0 0 0 # # # # #
# # # 1 1 # # # # G
# # # 1 1 # # # 1 1
# # 0 # # # # # 0 0
# 1 1 # # # # 0 0 1
# # # # # # # 0 1 0
# # # # # 1 1 0 0 0
# # # # 0 1 1 0 0 0
# 1 # 1 0 1 1 0 0 0
# 1 # 1 0 1 1 0 0 0
# # 0 0 0 0 0 0 0 0
S 0 0 0 0 0 0 0 0 0
0 1 0 0 0 1 1 0 0 0
0 0 0 0 0 1 1 0 0 0
Path Cost: 21
Now, the problem, as evident from the output, is that it is storing every index that gets visited (because heuristic values have very low difference for all the indexes, that is why, almost every node is being visited.. However, ultimately, A* search finds the best path, and that can be seen from "Path Cost: 21" which is the actual cost of the optimal path)
I believe that my algorithm is correct, considering the path cost but what I want now is store also the path of the optimal path.
For this, I want to keep a record of all the indexes (row and column) that are visited by one path.
For example, my path starts from
Row 11, Col 0
Then "optimal paths" goes to,
Row 10, Col 1 -> When I push these nodes into queue, I want to store "11, 0" as well. So that, I can know what path this node has taken previously to reach this state.
Following the same, then it will go to,
Row 9, Col 2 -> So, this node should also store both "11, 0" and "10, 1" in it, hence keeping record of the path it has taken so far.
And this goes on, until the "goal" node.
But I can't seem to find a way to implement this thing, something that keeps track of all the path every node has taken. In this way, I can easily avoid the problem I am facing (I will simply print the path the "goal node" took to reach that point, ignoring all the other nodes which were visited unnecessarily)
Can anyone help me in trying to find a logic for this?
Also, just to be clear, my class node and CompareCost have this implementation,
class node
{
public:
int i, j, heuristic, cost;
node() { i = j = heuristic = cost = 0; }
node(int heuristic, int i, int j, int cost) :i(i), j(j), heuristic(heuristic), cost(cost) {}
};
struct CompareCost {
bool operator()(node const& p1, node const& p2)
{
return p1.heuristic > p2.heuristic;
}
};
I am guessing that I need to store something extra in my "class node" but I can't seem to figure out the exact thing.
Construct your node like a linked list:
class node
{
public:
int i, j, cost;
node* next;
}
Add a method to the class to display the full path:
void ShowPath()
{
Node* temp = this;
do
{
if (temp != NULL)
{
std::cout << "(" << temp->i << ", " << temp->j << ")";
temp = temp->next;
}
} while (temp != NULL);
}
Last, modify A_search() so that it returns the new node definition. You can then call ShowPath() on the return value.
so I have 2 functions :
UPDATED
unordered_map<int, bool> visited2;
vector<vector<int>> elements2D;
bool DFSDetectCycle(int vertex){
s.push(vertex);
while(!s.empty()){
int np_vertex = s.top();
s.pop();
if (visited2[np_vertex] == true){
return true;
}
visited2[np_vertex] = true;
for (int i = 0; i<elements2D.size(); i++){
if(elements2D[np_vertex][i] != 0){
if(DFSDetectCycle(i)){
return true;
}
}
}
}
return false;
}
bool hasCycle(vector<vector<int>> v){
if (v.empty()){
return false;
}
for (int i = 0; i<v.size(); i++){
if (!visited2[i]){
if(DFSDetectCycle(i)){
return true;
}
}
}
return false;
}
And in my main function I call it like this:
if (hasCycle(elements2D)){
for (int i = 0; i<elements2D.size(); i++){
if (!visited2[i]){
DFSDetectCycle(i);
}
}
}else{
cout << "No cycles." << endl;
}
So basically, the input is going to look like this:
g++ -o GraphProcessor.o GraphProcessor.cpp -std=c++11
./GraphProcessor.o graph1.txt
And the output should look like this:
Connected components:
{0,1,2,4,7}
{3}
{5,6}
A cycle: 0 1 4 2
But my output looks like this:
Connected components:
{0,1,4,2,7}
{3}
{5,6}
No cycles.
graph1.txt looks like this:
0 2 6 0 0 0 0 3
2 0 0 0 4 0 0 1
6 0 0 0 3 0 0 2
0 0 0 0 0 0 0 0
0 4 3 0 0 0 0 0
0 0 0 0 0 0 7 0
0 0 0 0 0 7 0 0
3 1 2 0 0 0 0 0
Do not worry about the connected components part, that is not my problem right now. My problem is that my code is not properly detecting cycles in the graph and is not outputting them properly either. It seems as if my hasCycle() function is constantly giving a false statement, but I am not really sure why. elements2D is my matrix I am using, since it was read from a file, I needed somewhere to store it. For my visited2 function, I use an unordered_map in order to keep boolean values on whether or not I have visited the vertices or not. I know that if I have visited a vertex again, then I have a cycle. But I am not sure how to modify my algorithm in order to obtain a result like that.
Thanks again for any help.
You are calling DFSDetectCycle recursively without using it's return value. I suggest you check if recursive call return true, and return it is so.
You are specifically skipping the cycles because you filter the recursive calls with if(elements2D[np_vertex][i] != 0 && !visited2[i]) - which means you will not go into already visit vertexes, skipping the cycles.
In addition, there are no prints in the code that would yield the required output...
You should remove visited[i] checking from if(elements2D[np_vertex][i] != 0 && !visited2[i]), because if you already visited i, then removing this checking can detect it. And if it finds cycle, you should return it immediately.
if(elements2D[np_vertex][i] != 0){
if (DFSDetectCycle(i)) return true;
}
Another issue is if there exist edges 0->1 and 1->0, then they make a cycle. You need more work to find largest cycle.
I have been stuck with this problem for two days and I still can't get it right.
Basically, I have a 2D array with relations between certain numbers (in given range):
0 = the order doesn't matter
1 = the first number (number in left column) should be first
2 = the second number (number in upper row) should be first
So, I have some 2D array, for example this:
0 1 2 3 4 5 6
0 0 0 1 0 0 0 2
1 0 0 2 0 0 0 0
2 2 1 0 0 1 0 0
3 0 0 0 0 0 0 0
4 0 0 2 0 0 0 0
5 0 0 0 0 0 0 0
6 1 0 0 0 0 0 0
And my goal is to create a new array of given numbers (0 - 6) in such a way that it is following the rules from the 2D array (e.g. 0 is before 2 but it is after 6). I probably also have to check if such array exists and then create the array. And get something like this:
6 0 2 1 4 5
My Code
(It doesn't really matter, but I prefer c++)
So far I tried to start with ordered array 0123456 and then swap elements according to the table (but that obviously can't work). I also tried inserting the number in front of the other number according to the table, but it doesn't seem to work either.
// My code example
// I have:
// relArr[n][n] - array of relations
// resArr = {1, 2, ... , n} - result array
for (int i = 0; i < n; i++) {
for (int x = 0; x < n; x++) {
if (relArr[i][x] == 1) {
// Finding indexes of first (i) and second (x) number
int iI = 0;
int iX = 0;
while (resArr[iX] != x)
iX++;
while (resArr[iI] != i)
iI++;
// Placing the (i) before (x) and shifting array
int tmp, insert = iX+1;
if (iX < iI) {
tmp = resArr[iX];
resArr[iX] = resArr[iI];
while (insert < iI+1) {
int tt = resArr[insert];
resArr[insert] = tmp;
tmp = tt;
insert++;
}
}
} else if (relArr[i][x] == 2) {
int iI = 0;
int iX = 0;
while (resArr[iX] != x)
iX++;
while (resArr[iI] != i)
iI++;
int tmp, insert = iX-1;
if (iX > iI) {
tmp = resArr[iX];
resArr[iX] = resArr[iI];
while (insert > iI-1) {
int tt = resArr[insert];
resArr[insert] = tmp;
tmp = tt;
insert--;
}
}
}
}
}
I probably miss correct way how to check whether or not it is possible to create the array. Feel free to use vectors if you prefer them.
Thanks in advance for your help.
You seem to be re-ordering the output at the same time as you're reading the input. I think you should parse the input into a set of rules, process the rules a bit, then re-order the output at the end.
What are the constraints of the problem? If the input says that 0 goes before 1:
| 0 1
--+----
0 | 1
1 |
does it also guarantee that it will say that 1 comes after 0?
| 0 1
--+----
0 |
1 | 2
If so you can forget about the 2s and look only at the 1s:
| 0 1 2 3 4 5 6
--+--------------
0 | 1
1 |
2 | 1 1
3 |
4 |
5 |
6 | 1
From reading the input I would store a list of rules. I'd use std::vector<std::pair<int,int>> for this. It has the nice feature that yourPair.first comes before yourPair.second :)
0 before 2
2 before 1
2 before 4
6 before 0
You can discard any rules where the second value is never the first value of a different rule.
0 before 2
6 before 0
This list would then need to be sorted so that "... before x" and "x before ..." are guaranteed to be in that order.
6 before 0
0 before 2
Then move 6, 0, and 2 to the front of the list 0123456, giving you 6021345.
Does that help?
Thanks for the suggestion.
As suggested, only ones 1 are important in 2D array. I used them to create vector of directed edges and then I implemented Topological Sort. I decide to use this Topological Sorting Algorithm. It is basically Topological Sort, but it also checks for the cycle.
This successfully solved my problem.
I have an exercise for university where I have to write a DFS algorithm to run on an undirected graph. I also have to make the program sum the values of all nodes show the order in which the nodes were visited.
Here is the given structure:
#include <iostream>
#include <cassert>
using namespace std;
struct node {
// DATA STRUCTURE NODES
};
int dfs_sum(/* FUNCTION ARGUMENTS */) {
// DEPTH FIRST SEARCH ALGORITHM
}
void node_init(/* FUNCTION ARGUMENTS */) {
// INITIALIZATION OF NODE WITH LABEL "value" AND NEIGHBOR "num_adjacent"
}
void edge_init(/* FUNCTION ARGUMENTS */) {
// INITIALIZATION OF EDGE BETWEEN TWO NODES
}
void node_delete(/* FUNCTION ARGUMENTS */) {
// DE-ALLOCATE MEMORY THAT WAS ALLOCATED IN "node_init"
}
void init_nodes(node *nodes) {
node_init(&nodes[0], 1, 1);
node_init(&nodes[1], 2, 4);
node_init(&nodes[2], 3, 1);
node_init(&nodes[3], 4, 4);
node_init(&nodes[4], 5, 4);
node_init(&nodes[5], 6, 2);
node_init(&nodes[6], 7, 5);
node_init(&nodes[7], 8, 3);
node_init(&nodes[8], 9, 2);
node_init(&nodes[9], 10, 2);
node_init(&nodes[10], 11, 4);
node_init(&nodes[11], 12, 2);
edge_init(&nodes[0], &nodes[1]);
edge_init(&nodes[1], &nodes[4]);
edge_init(&nodes[1], &nodes[6]);
edge_init(&nodes[1], &nodes[7]);
edge_init(&nodes[2], &nodes[3]);
edge_init(&nodes[3], &nodes[6]);
edge_init(&nodes[3], &nodes[7]);
edge_init(&nodes[3], &nodes[11]);
edge_init(&nodes[4], &nodes[5]);
edge_init(&nodes[4], &nodes[8]);
edge_init(&nodes[4], &nodes[9]);
edge_init(&nodes[5], &nodes[6]);
edge_init(&nodes[6], &nodes[9]);
edge_init(&nodes[6], &nodes[10]);
edge_init(&nodes[7], &nodes[10]);
edge_init(&nodes[8], &nodes[10]);
edge_init(&nodes[10], &nodes[11]);
}
void delete_nodes(node *nodes) {
for (int i = 0; i < 12; ++i) {
node_delete(&nodes[i]);
}
}
int main() {
node *nodes= new node[12];
init_nodes(nodes);
int sum_dfs = dfs_sum(&nodes[0]);
cout << endl;
int sum_loop = 0;
for (int i = 0; i < 12; ++i) {
sum_loop += nodes[i].value;
}
cout << "sum_dfs = " << sum_dfs << " sum_loop = " << sum_loop << endl;
delete_nodes(nodes);
delete [] nodes;
return 0;
}
I do not know how to begin this exercise
I am not familiar with c++ (I think that's what you used) but the implementation is the same anyway so I can give you a pseudo-code of what the algorithm should look like.
create a stack where object will be stored
all nodes are not visited when we begin
push source in the stack and mark it as visited
while the stack is not empty;
go to the first adjacent node to source and if it has not been visited
mark as visited and move to its next unvisited node and so on
if at any point you reach a node that cannot visited any other unvisited node
pop the stack until you can visited an unvisited node.
Do this until the stack is empty
Below is a simple implementation using an adjacency matrix
void dfs(int adjacency_matrix[][], int source){
Stack<Integer> stack = new Stack<>();
int numNodes = adjacency_matrix[source].length -1;
boolean [] visited = new boolean[numNodes +1];
visited[source] = true;
stack.add(source);
while(!stack.isEmpty()){
int current = stack.peek(); // don't remove the element but get it
System.out.println("Current node being visited is "+current);
for(int x = 0; x <= numNodes; x++){
if(adjacency_matrix[current][x] == 1 && visited[x] == false){
visited[x] = true;
stack.push(x);
break;
}else if(x == numNodes){
stack.pop();
}
}
}
}
You can test with a graph like this
0 --- 1-------5----6--8
| \ \ | / /
| \ \ | / /
| \ \ | / /
2 3----4---7---9
0 1 2 3 4 5 6 7 8 9
---------------------
0 | 0 1 1 1 0 0 0 0 0 0
1 | 1 0 0 0 1 1 0 0 0 0
2 | 1 0 0 0 0 0 0 0 0 0
3 | 1 0 0 0 1 0 0 0 0 0
4 | 0 1 0 1 0 0 0 1 0 0
5 | 0 1 0 0 0 0 1 1 0 0
6 | 0 0 0 0 0 1 0 1 1 0
7 | 0 0 0 0 1 1 1 0 0 1
8 | 0 0 0 0 0 0 1 0 0 1
9 | 0 0 0 0 0 0 0 1 1 0
---------------------
So I have a lab to implement Breadth First Search and Depth First Search using an adjacency matrix. The vertices of the graph to be searched are numbered 0-(V-1), so for example a graph with 10 vertices would have vertices numbered 0-9. Each vertex is also given a value.
In the example I am going to give, the number of each vertex is equal to it's value (for example, vertex 0 has value 0, vertex 1 has value 1, etc.). I store the values of each vertex in an array, where the position is the vertex and the item in the array is it's value, so finding the value of vertex 7 would look like:
value = matrix[7];
I am supposed to write a program that finds a certain value with Breadth First Search and reports the vertex it was found at, and how many "steps" it took to find it.
My program finds the value in each test case, but the problem is that the "steps" don't match. I think the problem must be within my BFS algorithm itself, but I can't find it.
For example, I am searching the following adjacency matrix for value 7, which is at vertex 7:
0 1 1 0 0 0 0 0 0 0
0 0 0 1 1 0 0 0 0 0
0 0 0 0 0 1 1 0 0 0
0 0 0 0 0 0 0 1 1 0
0 0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
There are 10 nodes, numbered 0-9, node 0 is connected to nodes 1 and 2, node 1 is connected to nodes 3 and 4, node 2 is connected to nodes 5 and 6, node 3 is connected to nodes 7 and 8, and node 4 is connected to node 9.
As mentioned "vertices" is the array of vertex values. "matrix" is the adjacency matrix. "visited" is an array of bool to keep track of whether or not a vertex has been visited.
I am "walking" the graph with a deque container, which I am required to use.
Here is my BFS:
steps = 1;
int cur_v = 0;
int vertexFound = 0;
bool found = false;
bool *visited = new bool[V];
for (int i = 0; i < V; i++) {
visited[i] = false;
}
deque <int> q;
q.push_back(0);
visited[0] = true;
while (!q.empty()) {
if (found == false) {
steps++;
}
cur_v = q.front();
q.pop_front();
for (int n = 0; n < V; n++) {
if (matrix[cur_v][n] == 1) {
if (visited[n] == false) {
if (vertices[n] == search) {
vertexFound = n;
found = true;
}
visited[n] = true;
q.push_back(n);
}
}
}
}
if (found == true) {
cout << steps << endl;
}
The value I am searching for is "7", located at vertex 7. It is supposed to take 7 steps for me to get there, but my program says that it takes 5.
Another problem I am having is that when I give the program input that is supposed to make it search for value 8 in a graph with 8 vertices that go from values 0-7, it tells me that it found the value at vertex 0 in 9 steps.
Any help is very appreciated!
You shouldn't be updating vertexFound after the first time you find what you're looking for. (And indeed you could just stop searching immediately.)