edge connectivity graph - c++

I need help with a pseudocode for an algorithm that solves the 3-edge connectivity problem:
input: a graph G in adjacency matrix format
output: true if, for every pair of vertices v,w elements of G, there exists a path from v to w of length at most 3
Any Ideas? This is what I have so far.
const int WIDTH = 10;
const HIGHT =10;
Int arrayMatrix [WIDTH] [HIGHT];
for (int i =0; i< WIDTH; i++)
{
for (int j =0; j<HIGHT; j++)
{
int countEdges =0;
countEdges = countEdges +arrayMatrix [i];
}
if countEdges<=3
cout << "True for 3-edge connectivity problem" << endl;
else
cout <<"Not found" << enld;

you can use a technique similar to the Warshall-Floyd algorithm, to compute G^3, but where for matrix multiplication you have the following operation
(X * Y)ij = OR [all k] (Xik AND Ykj).
now compute (G*G)*G (with your input adjacency matrix).
Return true if the result matrix contains only 'true' elements.

Related

Program for finding the transpose of given matrix

I was thinking the approach to finding the transpose of a matrix and
below is the algorithm but it is not giving me proper output , so
anyone can tell me where I have done mistake and what should be proper
algorithm ? And how can I improve it ?
// m is the number of rows and n is the number of columns in a matrix
for (int i = 0; i < m; i++) // For swapping the non-diagonal elements
{
for (int j = 0; j < n; j++)
{
if (i != j)
{
int temp = 0;
temp = a[i][j];
a[i][j] = a[j][i];
a[j][i] = temp;
}
}
}
cout << "Elements of transpose matrix of a is: " << endl;
for (int i = 0; i < m; i++) // printing the elements after transpose
{
for (int j = 0; j < n; j++)
{
cout << a[i][j] << " ";
}
cout << endl;
You made the same mistake one can make while reversing a 1D array, hence I will use that as a simpler example:
#include <vector>
#include <iostream>
#include <utility>
std::vector<int> reverse_broken(std::vector<int> x){
for (size_t i=0;i< x.size(); ++i){
std::swap(x[i],x[x.size()-1-i]);
}
return x;
}
int main(){
auto x = reverse_broken({1,2,3,4});
for (const auto& e : x) std::cout << e << " ";
}
output:
1 2 3 4
reverse_broken iterates all elements and swaps them with the respective reversed element. However, once the first has been swapped with the last, the last has already been swapped. Later swapping the last with the first puts them in the original order again.
Same with your transpose. Once you swapped an element above the diagonal with one below the diagonal, they are already transposed. You don't need to swap them again.
I'll show you the fix for the reverse_broken and leave it to you to apply same fix to your transpose:
std::vector<int> reverse(std::vector<int> x){
for (size_t i=0;i< x.size()/2; ++i){
// stop in the middle ^^ because then all elements have been swapped
std::swap(x[i],x[x.size()-1-i]);
}
return x;
}
You should also consider to not transpose the matrix at all. Depending on how often you access swapped elements and how you populate it, it will be cheaper to either populate it in right order from the start, or just swapping the indices on access:
// normal access:
auto x = a[i][j];
// transposed access:
auto y = a[j][i];
PS: I used reverse only for illustration. To reverse a container you should actually use std::reverse. Also note that you can and should use std::swap. And last but not least, only a square matrix can be transposed in place. For a non square matrix you need to construct a new one with different dimensions.

How to add a block matrix onto a sparse matrix in Eigen

For example I have a 10x10 SparseMatrix A, and I want to add a 3x3 identity matrix to the upper left corner of A.
A is known to be already non-zero in those 3 entries.
If I have to add the values one by one it is ok too, but I didn't find the method to manipulate on elements of a Sparse Matrix in Eigen.
Did I miss something?
If all you want is to apply an operation to a specific element at a time, you can use coeffRef like so:
typedef Eigen::Triplet<double> T;
std::vector<T> coefficients;
for (int i = 0; i < 9; i++) coefficients.push_back(T(i, i, (i % 3) + 1));
Eigen::SparseMatrix<double> A(10, 10);
A.setFromTriplets(coefficients.begin(), coefficients.end());
std::cout << A << "\n\n";
for (int i = 0; i < 3; i++) A.coeffRef(i,i) += 1;
std::cout << A << "\n\n";

Generating random Graph

Have someone input an integer N as the number of vertices in the graph.
Assign random weights on each edges ranging from 1 to 10. Not all possible edges
are present though! As in the above example, represented an absent edge by an X.
Return a pair (M,L), with M and L respectively being the matrix and list representation
of the (same) random graph you are generating.
Use non-digit characters as vertex names, to avoid confusion with edge weights.
#include <iostream>
#include <stdlib.h>
using namespace std;
void gen_random_graph(int n)
{
int adj_matrix[n][n];
for(int u = 0; u < n; u++)
{
for (int v = 0; v < n; v++)
{
if(adj_matrix[u][v]==adj_matrix[v][u])
{
adj_matrix[u][v] = rand() % 10 + 1;
cout << adj_matrix[u][v] << endl;
}
}
}
}
int main()
{
int N;
cout << "enter number of vertices" << endl;
cin >> N;
gen_random_graph(N);
return 0;
}
THis is my code so far. Is it generateing the weights ? and what does it mean i have to return a pair?
A graph can be represented as an N x N adjacency matrix (as you have already set up), where the value in matrix[i][j] corresponds to the weight of the edge connecting vertex i to vertex j. A zero corresponds to there not being a connection between i and j. If matrix[i][j] == matrix[j][i], then you have an undirected graph. Furthermore, a random graph would have random values as the edges between vertices.
In the case where every edge either exists or doesn't exist (i.e. weights are either 0 or 1), you could have the following:
This image is stolen from the internet, so I take no credit for it. Note that you can easily confirm that the first graph is undirected because the adjacency matrix is symmetric. Likewise, the second graph is directed because the matrix is NOT symmetric.

adjacency list error with list

Basically i generated a adj_matrix and i want to make an adj_list from the adj_matrix...However I keep getting an error saying "no match for call..."
i tried it without aPair i still get the same error i can't seem to figure out what my problem is. Can anyone tell me why list isn't working? the list is at the very end of the code
int **gen_random_graph(int n)
{
srand(time(0));
int **adj_matrix = new int*[n];
for(int i = 0; i < n; i++)
{
for (int j = i; j < n; j++) //generating a N x N matrix based on the # of vertex input
{
adj_matrix[i] = new int[n];
}
}
for(int u = 0; u < n; u++)
{
for (int v = u; v < n; v++)
{
bool edgeOrNot = rand() % 2; //decide whether it has an edge or not
adj_matrix[u][v] = adj_matrix[v][u] = edgeOrNot;
if(adj_matrix[u][v] == true)
{
adj_matrix[v][u] = true;
if(u == v) //We can't have i = j in an undirected graph so we set it to false
{
adj_matrix[u][v] = -1;
}
}
else //if adj_matrix[u][v] is false set the symmetry to be false
{
adj_matrix[v][u] = adj_matrix[u][v] = -1;
}
}
}
for(int i = 0; i < n; i++)
{
for(int j = i; j < n; j++) //create the N x N with edges and sets the weight between the edge randomly
{
if(adj_matrix[i][j] == true)
{
int weight = rand() % 10 + 1;
adj_matrix[i][j] = adj_matrix[j][i] = weight;
cout << " ( " << i << "," << j << " ) " << "weight: " << adj_matrix[i][j] << endl;
}
}
}
for(int i = 0; i < n; i++)
{
vector<int> adj_list;
for(int j = i; j < n; j++)
{
if(adj_matrix[i][j] > 0)
{
int weight = adj_matrix[i][j];
adj_list.push_back(j);
cout << adj_list[i] << " " << endl;
}
}
}
print(n,adj_matrix);
return (adj_matrix);
}
I see that adj_list is not callable, so your code there is broken. There are a couple simple solutions to that. Taking a look at these docs, you may simply either access listObj.front() and listObj.back() OR you may also just create an iterator using listObj.begin() and iterating over the two elements (which may be desirable if you ever decide to put more than two elements in the list). See this tutorial for a simple example on creating an iterator for a list, in the code snippet right above the summary.
Note, here, your list object which I called listObj for simplicity/abstraction would simply be adj_matrix[i][j] in that bottom loop. That should fix your syntax error.
Also, aside from the syntax of your code, I don't get why you're trying to push weights to a list, then you're printing out and returning the adjacency matrix. I also don't get why you would use lists of pair objects when it seems like you only want to push integer weights onto it. For that, you can use a simple vector of integers (i.e.: vector <int> adj_list;)... or even simpler, you could use a simple array of integers... rather than using a vector of lists of pairs.
EDIT: After running the code locally and taking a look at the values, I realized the issue a bug in the OP's output was simply that he was using "true" in C++ in place of an integer, which was creating a bug, as explained in this SO post. The OP also has a further design decision to make where adjacency lists are concerned. More on what an adjacency list is, conceptually, found on Wikipedia.

How to input an matrix style txt file instead of defining my own int 2D array for C++

So I'm pretty new to C++ but i think im gettting the hang of it a bit.
As part of an excersize, I have to take an input text file and apply this in a "shortest distance algorithm" where ultimatly I want to output all the shortest distances and routes but i haven't gotten that far yet. I have used the Floyd Warshall algorithm.
For now my question is, how do i replace a self written int array by a text input. the input array is just numbers but actually represents distances between nodes. The test array that im using now only has 3 nodes, but i want to be able to expand it to a much larger node amout, say 100.
example test matrix:
0 1234567 100
1234567 0 400
100 400 0
Should be read as:
node1 node2 node3
node 1 0 999999 100
node 2 999999 0 400
node 3 100 400 0
The large numbers: 999999 represents a distance that is too large too count as a edge.
As of now my code looks something like this:
#include<stdio.h>
// Number of vertices
#define V 3
// Define 999999 as a distance that is too large to represent a edge connection
#define TooLarge 999999
// The print function
void printSolution(int dist[][V]);
// Distance algorithm
void Distance (int distgraph[][V])
{
// output matrix that will have the shortest distance for every vertice
int dist[V][V], i, j, k;
// initial values for shortest distance are based on shortest paths.
for (i = 0; i < V; i++)
for (j = 0; j < V; j++)
dist[i][j] = distgraph[i][j];
// Add all vertices to the set of intermediate vertices.
for (k = 0; k < V; k++)
{
// use all vertices as seperate source
for (i = 0; i < V; i++)
{
// use all vertices as destination for the earlier determined source
for (j = 0; j < V; j++)
{
// If vertex k is on the shortest path from i to j, then update the value of dist[i][j]
if (dist[i][k] + dist[k][j] < dist[i][j])
dist[i][j] = dist[i][k] + dist[k][j];
}
}
}
// Print the shortest distance matrix
printSolution(dist);
}
// The print function
void printSolution(int dist[][V])
{
printf ("Shortest distance matrix \n");
for (int i = 0; i < V; i++)
{
for (int j = 0; j < V; j++)
{
if (dist[i][j] == 999999)
printf("%7s", "TooLarge");
else
printf ("%7d", dist[i][j]);
}
printf("\n");
}
}
// driver program to test above function
int main()
{
int distgraph[V][V] = { {0, 1234567, 100},
{1234567, 0, 400},
{100, 400, 0,},
};
// Print the solution
Distance(distgraph);
return 0;
}
Hopefully someone can help me, I have the feeling im just forgetting something stupid. I have tried to inport the textfile using this type of code:
using namespace std;
double distances [3][3];
int main () {
int x, y;
ifstream in("citytest.txt");
if (!in) {
cout << "Cannot open file.\n";
return 0;
}
for (y = 0; y < 3; y++) {
for (x = 0; x < 3; x++) {
in >> distances[x][y];
}
}
cout << distances[3][3] << " " << endl;
in.close();
Which i know works, but only inports a predetermind part of the matrix whereas i want to input the entire array. (the cout function is just there to test if the correct distances were given as an input)
You cannot efficiently allocate the container unless you know big the workload in your external data file is.
Thus:
tokenize the first line of your file and take the dimension N from that
allocate your container accordingly
then consume the rest of the file and put the data into the container; maybe throw if a row's length doesn't match N, or if there are not N rows.
You may consider that
representing a graph by a full adjacency matrix is a debatable concept; it's space-inefficient and time-inefficient for sparse graphs
a 2D c-array is not the only possible representation of a matrix; you may consider a flat std container and implement a slice-style access on it
last not least you may want to have a look at boost::graph