Path finding in an undirected graph - c++

I'm trying to list all the paths in an undirected graph, and my question is similar to this question. I've tried to run this code, but it loops indefinitely -- I ran it with 60 nodes. Any ideas on how to produce the correct solution?
I added such a random graph and the code is now like:
#include<stdio.h>
static struct {
int value1;
int value2;
int used;
} data[] = {
{ 1, 2 },
{ 1, 5 },
{ 2, 3 },
{ 2, 6 },
{ 3, 7 },
{ 4, 0 },
{ 0, 4 },
{ 7, 3 },
{ 2, 1 },
};
enum { DATA_SIZE = sizeof data / sizeof *data };
static int output[DATA_SIZE];
int traverse(int from, int to, int depth) {
output[depth++] = from;
int i;
if (from == to) {
for (i = 0; i < depth; i++) {
if (i) {
printf("-");
}
printf("%d", output[i]);
}
printf("\n");
} else {
for (i = 0; i < DATA_SIZE; i++) {
if (!data[i].used) {
data[i].used = 1;
if (from == data[i].value1) {
traverse(data[i].value2, to, depth);
} else if (from == data[i].value2) {
traverse(data[i].value1, to, depth);
}
data[i].used = 0;
}
}
}
}
int main() {
traverse(1, 7, 0);
}`
And the output is:
1-2-3-7
1-2-3-7
1-2-3-7
1-2-3-7
Why do I get that path 4 times? Is it possible to fix? thanks

You can not fix it. The number of paths in graph (not counting sparse graphs) is exponential by itself and only outputting will take forever. Clearly, it's impossible. Even if your graph is sparse (but connected) there will be at least O(N^2) paths.

As I understand the algorithm you link to, it will visit the same vertex multiple times (it will not visit the same edge multiple times, though). This means that the maximum length of one path is proportional to the number of edges in your graph, not the number of nodes. You say your graph has 60 nodes - how many edges? If that number is very large, then it may run for a very long time to produce even a single path.
You could modify the algorithm slightly to only visit each node once, but that may not be what you're looking for.

Related

Linear Search on Vector

I have tests to pass online using my created methods. I have a feeling there is an issue with one of the tests. The final one i cannot pass.
Here is the test-
TEST_CASE ("Linear Search With Self-Organization 3") {
int searchKey = 191;
vector<int> searchArray(500);
for (int i = 0; i < 500; i++) {
searchArray[i] = i + 1;
}
random_shuffle(searchArray.begin(), searchArray.end());
bool result, result2;
result = linearSearchSO(searchArray, searchKey);
int searchKey2 = 243;
result2 = linearSearchSO(searchArray, searchKey2);
REQUIRE (result == true);
REQUIRE (result2 == true);
REQUIRE (verifySearchArray(searchArray) == true);
REQUIRE (searchArray[0] == searchKey2);
REQUIRE (searchArray[1] == searchKey);
REQUIRE (searchArray.size() == 500);
}
The method in question here is linearSearchSO.
bool linearSearchSO(vector<int> & inputArr, int searchKey) {
printArray(inputArr);
for(int i=0; i < inputArr.size(); i++) {
int temp = inputArr[0];
if (inputArr[i] == searchKey) {
inputArr[0] = inputArr[i];
inputArr[i] = temp;
printArray(inputArr);
return true;
}
}
return false;
}
Worth noting that this method has passed all 3 of the other tests required. As you can see in the test, my tutor has called this method twice passing two different values.The idea is that there is a vector of 500 numbers.. In this instance he randomises the numbers. The best way for me to explain what is happening is that if he didn't randomise and the numbers were simply listed 1-500. The method gets called and I begin with the requested number 191, I move this to front of the vector.
Now it reads 191, 2, 3, 4 etc. 190, 1, 192 etc.
So he then calls the method again, and wants 243 to be moved to the front. His test wants the result to be 243, 191, 2, 3, 4. However what my code does is swap 191 to 243's position.
My result now reads 243, 2, 3, 4 etc. 242, 191, 244, 245 etc.
Every other test is simply taking one number and moving it to the front, the test then checks that each number is in the correct position. My question is, is there a way for me to achieve 243, 191, 2, 3.. without messing up every other test I've passed only using this one linearSearch function? or is there a problem with the test, and hes simply made a mistake.
EDIT- The actual question asked for this test.
Question 4
A self-organising search algorithm is one that rearranges items in a collection such that those items that are searched frequently are likely to be found sooner in the search. Modify the learning algorithm for linear search such that every time an item is found in the array, that item is exchanged with the item at the beginning of the array.
If I have understood correctly you need something like the following
#include <iostream>
#include <vector>
bool linearSearchSO( std::vector<int> & inputArr, int searchKey )
{
bool success = false;
auto it = inputArr.begin();
while ( it != inputArr.end() && *it != searchKey ) ++it;
if ( ( success = it != inputArr.end() ) )
{
int value = *it;
inputArr.erase( it );
inputArr.insert( inputArr.begin(), value );
}
return success;
}
int main()
{
std::vector<int> inputArr = { 1, 2, 3, 4, 5 };
for ( const auto &item : inputArr )
{
std::cout << item << ' ';
}
std::cout << '\n';
linearSearchSO( inputArr, 3 );
for ( const auto &item : inputArr )
{
std::cout << item << ' ';
}
std::cout << '\n';
}
The program output is
1 2 3 4 5
3 1 2 4 5
Pay attention to that instead of writing manually a loop in the function you could use the standard algorithm std::find.

Why does push_back into vector<vector<int>> causing seg fault?

Want to construct a Graph with adjacency list, but getting seg-fault when I add elements to vector<vector<int>>. adj.size() prints 5 which tells it has allocated memory, why the seg-fault in addEdge() method?
#define V 5
struct Edge {
int src, dst;
};
void addEdge(vector<vector<int>> &adj, int u, int v)
{
adj[u].push_back(v);
}
void constructGraph(vector<vector<int>> &adj, vector<Edge> &edges)
{
for(Edge e : edges)
{
addEdge(adj, e.src, e.dst);
}
}
int main()
{
vector<vector<int>> adj(V);
vector<Edge> edges =
{
{ 0, 1 }, { 1, 2 }, { 2, 0 }, { 2, 1 },
{ 3, 2 }, { 4, 5 }, { 5, 4 }
};
constructGraph(adj, edges);
return 0;
}
void addEdge(vector<vector<int>> &adj, int u, int v)
{
adj[u].push_back(v);
}
is incorrect. The operator[]() for a vector ASSUMES the supplied index is valid. If u is not valid, the behaviour is undefined.
In your code, the vector passed has five elements, and the last edge in main()
vector<Edge> edges =
{
{ 0, 1 }, { 1, 2 }, { 2, 0 }, { 2, 1 },
{ 3, 2 }, { 4, 5 }, { 5, 4 } // note the last pair here
};
will cause addEdge() to be called with u having a value of 5. That is one past the end.
While #define V 6 will fix the problem, it doesn't protect addEdge() from being passed a bad value of u. Instead I would implement addEdge() so it protects itself from bad data as follows.
void addEdge(vector<vector<int>> &adj, int u, int v)
{
if (u < 0) return; // handle negative u
if (u >= adj.size()) adj.resize(u+1); // resize if needed
adj[u].push_back(v);
}
An even better approach would be to avoid using supplied data - such as the data in edges in your main() - as array indices at all.
Solved. Thanks for the guidance provided here, read up more on this and learnt that c++ language has protection built into it for these kinds of issues. Using .at() method protects the programmer from out-ob-bounds accesses.
void addEdge(vector<vector<int>> &adj, int u, int v)
{
adj.at(u).push_back(v);
}
if you use adj.at(u) instead of adj[u], program exits little gracefully
terminate called after throwing an instance of 'std::out_of_range'
what(): vector::_M_range_check: __n (which is 5) >= this->size() (which is 5)
Aborted (core dumped)

Generating Trees

I'm trying to generate valid trees given certain graph edges (which can be considered as a network). Following is the code which reads the graph edges from a file;
FILE *fin = fopen("somefile.txt", "r");
for (int i = 0; i <=edges; i++) {
fscanf(fin, "%d%d%d", &u, &v, &w);
graph[u][v]=w;
}
fclose(fin);
Now I want to generate the maximum number of possible trees (or topology) for a given root u and a given size N given these edges.
For example, if there are edges; 1--->2 ;1--->3; 3--->4. Now if N is 1; possible trees from u=1 is 1---->2 and 1--->3. If N is 2, then possible trees are 1--->2 & 3 or 1--->3---->4
What would be the best way of achieving this? I'm not concerned about complexity issues. I'll appreciate the help!
it may not the best implementation but
something like this should work
map<vertex,list<edge>> vertexToedgeThatIncludeIt
void Coloredge(edgeList)
{
for each edge in list:
edge.color=True
}
void init()
{
for each edge:
{
vertexToedgeThatIncludeIt[edge.vertex1].append(edge)
vertexToedgeThatIncludeIt[edge.vertex2].append(edge)
}
}
edge* findUnColoredvertex(edgeList,startPoistion,founfAt)
{
skip to startPoistion
for each edge In edgeList:
if edge not colored return edge
update founfAt
return NULL
}
void spanTree(vertexToedgeThatIncludeIt,spanTreeList,lastvertex)
{
if(spanTreeList.size==NumberOfTotalvertex)
{
print spanningTree
return
}
nextedge=findUnColoredvertex(vertexToedgeThatIncludeIt[lastvertex],0,founfAt)
while(nextedge!=NULL)
{
spanTreeList.append(nextedge);
Coloredge(vertexToedgeThatIncludeIt[lastvertex]);
spanTree(vertexToedgeThatIncludeIt,spanTreeList,nextedge.othervertex)
spanTreeList.pop();
UnColoredge(vertexToedgeThatIncludeIt[lastvertex])
nextedge=findUnColoredvertex(vertexToedgeThatIncludeIt[lastvertex],founfAt,founfAt)
}
}

Using recursion and backtracking to generate all possible combinations

I'm trying to implement a class that will generate all possible unordered n-tuples or combinations given a number of elements and the size of the combination.
In other words, when calling this:
NTupleUnordered unordered_tuple_generator(3, 5, print);
unordered_tuple_generator.Start();
print() being a callback function set in the constructor.
The output should be:
{0,1,2}
{0,1,3}
{0,1,4}
{0,2,3}
{0,2,4}
{0,3,4}
{1,2,3}
{1,2,4}
{1,3,4}
{2,3,4}
This is what I have so far:
class NTupleUnordered {
public:
NTupleUnordered( int k, int n, void (*cb)(std::vector<int> const&) );
void Start();
private:
int tuple_size; //how many
int set_size; //out of how many
void (*callback)(std::vector<int> const&); //who to call when next tuple is ready
std::vector<int> tuple; //tuple is constructed here
void add_element(int pos); //recursively calls self
};
and this is the implementation of the recursive function, Start() is just a kick start function to have a cleaner interface, it only calls add_element(0);
void NTupleUnordered::add_element( int pos )
{
// base case
if(pos == tuple_size)
{
callback(tuple); // prints the current combination
tuple.pop_back(); // not really sure about this line
return;
}
for (int i = pos; i < set_size; ++i)
{
// if the item was not found in the current combination
if( std::find(tuple.begin(), tuple.end(), i) == tuple.end())
{
// add element to the current combination
tuple.push_back(i);
add_element(pos+1); // next call will loop from pos+1 to set_size and so on
}
}
}
If I wanted to generate all possible combinations of a constant N size, lets say combinations of size 3 I could do:
for (int i1 = 0; i1 < 5; ++i1)
{
for (int i2 = i1+1; i2 < 5; ++i2)
{
for (int i3 = i2+1; i3 < 5; ++i3)
{
std::cout << "{" << i1 << "," << i2 << "," << i3 << "}\n";
}
}
}
If N is not a constant, you need a recursive function that imitates the above
function by executing each for-loop in it's own frame. When for-loop terminates,
program returns to the previous frame, in other words, backtracking.
I always had problems with recursion, and now I need to combine it with backtracking to generate all possible combinations. Any pointers of what am I doing wrong? What I should be doing or I am overlooking?
P.S: This is a college assignment that also includes basically doing the same thing for ordered n-tuples.
Thanks in advance!
/////////////////////////////////////////////////////////////////////////////////////////
Just wanted to follow up with the correct code just in case someone else out there is wondering the same thing.
void NTupleUnordered::add_element( int pos)
{
if(static_cast<int>(tuple.size()) == tuple_size)
{
callback(tuple);
return;
}
for (int i = pos; i < set_size; ++i)
{
// add element to the current combination
tuple.push_back(i);
add_element(i+1);
tuple.pop_back();
}
}
And for the case of ordered n-tuples:
void NTupleOrdered::add_element( int pos )
{
if(static_cast<int>(tuple.size()) == tuple_size)
{
callback(tuple);
return;
}
for (int i = pos; i < set_size; ++i)
{
// if the item was not found in the current combination
if( std::find(tuple.begin(), tuple.end(), i) == tuple.end())
{
// add element to the current combination
tuple.push_back(i);
add_element(pos);
tuple.pop_back();
}
}
}
Thank you Jason for your thorough response!
A good way to think about forming N combinations is to look at the structure like a tree of combinations. Traversing that tree then becomes a natural way to think about the recursive nature of the algorithm you wish to implement, and how the recursive process would work.
Let's say for instance that we have the sequence, {1, 2, 3, 4}, and we wish to find all the 3-combinations in that set. The "tree" of combinations would then look like the following:
root
________|___
| |
__1_____ 2
| | |
__2__ 3 3
| | | |
3 4 4 4
Traversing from the root using a pre-order traversal, and identifying a combination when we reach a leaf-node, we get the combinations:
{1, 2, 3}
{1, 2, 4}
{1, 3, 4}
{2, 3, 4}
So basically the idea would be to sequence through an array using an index value, that for each stage of our recursion (which in this case would be the "levels" of the tree), increments into the array to obtain the value that would be included in the combination set. Also note that we only need to recurse N times. Therefore you would have some recursive function whose signature that would look something like the following:
void recursive_comb(int step_val, int array_index, std::vector<int> tuple);
where the step_val indicates how far we have to recurse, the array_index value tells us where we're at in the set to start adding values to the tuple, and the tuple, once we're complete, will be an instance of a combination in the set.
You would then need to call recursive_comb from another non-recursive function that basically "starts off" the recursive process by initializing the tuple vector and inputting the maximum recursive steps (i.e., the number of values we want in the tuple):
void init_combinations()
{
std::vector<int> tuple;
tuple.reserve(tuple_size); //avoids needless allocations
recursive_comb(tuple_size, 0, tuple);
}
Finally your recusive_comb function would something like the following:
void recursive_comb(int step_val, int array_index, std::vector<int> tuple)
{
if (step_val == 0)
{
all_combinations.push_back(tuple); //<==We have the final combination
return;
}
for (int i = array_index; i < set.size(); i++)
{
tuple.push_back(set[i]);
recursive_comb(step_val - 1, i + 1, tuple); //<== Recursive step
tuple.pop_back(); //<== The "backtrack" step
}
return;
}
You can see a working example of this code here: http://ideone.com/78jkV
Note that this is not the fastest version of the algorithm, in that we are taking some extra branches we don't need to take which create some needless copying and function calls, etc. ... but hopefully it gets across the general idea of recursion and backtracking, and how the two work together.
Personally I would go with a simple iterative solution.
Represent you set of nodes as a set of bits. If you need 5 nodes then have 5 bits, each bit representing a specific node. If you want 3 of these in your tupple then you just need to set 3 of the bits and track their location.
Basically this is a simple variation on fonding all different subsets of nodes combinations. Where the classic implementation is represent the set of nodes as an integer. Each bit in the integer represents a node. The empty set is then 0. Then you just increment the integer each new value is a new set of nodes (the bit pattern representing the set of nodes). Just in this variation you make sure that there are always 3 nodes on.
Just to help me think I start with the 3 top nodes active { 4, 3, 2 }. Then I count down. But it would be trivial to modify this to count in the other direction.
#include <boost/dynamic_bitset.hpp>
#include <iostream>
class TuppleSet
{
friend std::ostream& operator<<(std::ostream& stream, TuppleSet const& data);
boost::dynamic_bitset<> data; // represents all the different nodes
std::vector<int> bitpos; // tracks the 'n' active nodes in the tupple
public:
TuppleSet(int nodes, int activeNodes)
: data(nodes)
, bitpos(activeNodes)
{
// Set up the active nodes as the top 'activeNodes' node positions.
for(int loop = 0;loop < activeNodes;++loop)
{
bitpos[loop] = nodes-1-loop;
data[bitpos[loop]] = 1;
}
}
bool next()
{
// Move to the next combination
int bottom = shiftBits(bitpos.size()-1, 0);
// If it worked return true (otherwise false)
return bottom >= 0;
}
private:
// index is the bit we are moving. (index into bitpos)
// clearance is the number of bits below it we need to compensate for.
//
// [ 0, 1, 1, 1, 0 ] => { 3, 2, 1 }
// ^
// The bottom bit is move down 1 (index => 2, clearance => 0)
// [ 0, 1, 1, 0, 1] => { 3, 2, 0 }
// ^
// The bottom bit is moved down 1 (index => 2, clearance => 0)
// This falls of the end
// ^
// So we move the next bit down one (index => 1, clearance => 1)
// [ 0, 1, 0, 1, 1]
// ^
// The bottom bit is moved down 1 (index => 2, clearance => 0)
// This falls of the end
// ^
// So we move the next bit down one (index =>1, clearance => 1)
// This does not have enough clearance to move down (as the bottom bit would fall off)
// ^ So we move the next bit down one (index => 0, clearance => 2)
// [ 0, 0, 1, 1, 1]
int shiftBits(int index, int clerance)
{
if (index == -1)
{ return -1;
}
if (bitpos[index] > clerance)
{
--bitpos[index];
}
else
{
int nextBit = shiftBits(index-1, clerance+1);
bitpos[index] = nextBit-1;
}
return bitpos[index];
}
};
std::ostream& operator<<(std::ostream& stream, TuppleSet const& data)
{
stream << "{ ";
std::vector<int>::const_iterator loop = data.bitpos.begin();
if (loop != data.bitpos.end())
{
stream << *loop;
++loop;
for(; loop != data.bitpos.end(); ++loop)
{
stream << ", " << *loop;
}
}
stream << " }";
return stream;
}
Main is trivial:
int main()
{
TuppleSet s(5,3);
do
{
std::cout << s << "\n";
}
while(s.next());
}
Output is:
{ 4, 3, 2 }
{ 4, 3, 1 }
{ 4, 3, 0 }
{ 4, 2, 1 }
{ 4, 2, 0 }
{ 4, 1, 0 }
{ 3, 2, 1 }
{ 3, 2, 0 }
{ 3, 1, 0 }
{ 2, 1, 0 }
A version of shiftBits() using a loop
int shiftBits()
{
int bottom = -1;
for(int loop = 0;loop < bitpos.size();++loop)
{
int index = bitpos.size() - 1 - loop;
if (bitpos[index] > loop)
{
bottom = --bitpos[index];
for(int shuffle = loop-1; shuffle >= 0; --shuffle)
{
int index = bitpos.size() - 1 - shuffle;
bottom = bitpos[index] = bitpos[index-1] - 1;
}
break;
}
}
return bottom;
}
In MATLAB:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% combinations.m
function combinations(n, k, func)
assert(n >= k);
n_set = [1:n];
k_set = zeros(k, 1);
recursive_comb(k, 1, n_set, k_set, func)
return
function recursive_comb(k_set_index, n_set_index, n_set, k_set, func)
if k_set_index == 0,
func(k_set);
return;
end;
for i = n_set_index:length(n_set)-k_set_index+1,
k_set(k_set_index) = n_set(i);
recursive_comb(k_set_index - 1, i + 1, n_set, k_set, func);
end;
return;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Test:
>> combinations(5, 3, #(x) printf('%s\n', sprintf('%d ', x)));
3 2 1
4 2 1
5 2 1
4 3 1
5 3 1
5 4 1
4 3 2
5 3 2
5 4 2
5 4 3

What is wrong with my dijkstras algorithm

So I've been working on this for hours and I'm extremely frustrated. I don't understand what I'm doing wrong.
I'm using Dijkstra's Algorithm to find the shortest paths between a source vertex, and 4 other vertices using an adjacency matrix. The idea behind this is that there are 5 cities and flights going to and from them, and I need to find the cheapest ticket price, taking into account layovers.
I'm following the algorithm out of my book, which is in pseudocode, and the code on the following website: http://vinodcse.wordpress.com/2006/05/19/code-for-dijkstras-algorithm-in-c-2/
The problem I'm having is that in the nested for loop on the website, the counter i starts at 1, and I believe this is the reason why the distances from the source vertex to all the vertices are correct, except the first one which is unchanged at 999.
Example:
Current Distance: 999 220 0 115 130
Predecessors: 0 3 0 2 2
All of those distances are correct--even if I change the source vertex--except for the first one which remains unchanged.
If I change the counter i to 0, it messes up every distance, i.e.
Current Distance: 0 105 0 0 0
Anyway, Please help. Here is the relevant code.
void Graph::findDistance(int startingVertex)
{
for(int i=0; i<MAX;i++)
{
currentDistance[i] = 999;
toBeChecked[i] = 1;
predecessor[i] = 0;
}
currentDistance[startingVertex]=0;
bool flag=true;
int v;
while(flag)
{
v=minimum();
toBeChecked[v]=0;
for(int i=1; i<MAX;i++) //here is where i think im going wrong
{
if(adjecencyMatrix[v][i]>0)
{
if(toBeChecked[i]!=0)
{
if(currentDistance[i] > currentDistance[v]+adjecencyMatrix[v][i][0].ticketPrice)
{
currentDistance[i] = currentDistance[v]+adjecencyMatrix[v][i][0].ticketPrice;
predecessor[i]=v;
}
}
}
}
flag = false;
for(int i=1; i<MAX;i++)
{
if(toBeChecked[i]==1)
flag=true;
}
}
}
int Graph::minimum()
{
int min=999;
int i,t;
for(i=0;i<MAX;i++)
{
if(toBeChecked[i]!=0)
{
if(min>=currentDistance[i])
{
min=currentDistance[i];
t=i;
}
}
}
return t;
}
Shouldn't this check
if(adjecencyMatrix[v][i]>0)
be done with adjecencyMatrix[v][i][0].ticketPrice, like the rest of the comparisons?
If adjecencyMatrix[v][i] is an array, it is getting converted to a pointer, and that pointer will always compare greater than 0. Array-to-pointer decay strikes again :)