optimization in brute force vertex cover algorithm - c++

I'm writing a brute-force algorithm to solve vertex cover like this:
BruteForceVertexCover( Graph G = (V,E) ){
for size= 1 ... |V|
vector<int> v = {0...size-1}
do{
if(test(G, v)) return v; //test if v covers G
}
while(v has next combinations of lenght size);
return empty vector<int>;
}
//this stops when find a answer, and it will find,
//since it tries all combinations of all sizes
where
bool test( Graph G = (V,E), vector<int> v ){
for each u in v:
for each w in G[u]
remove u from G[w] //this is linear in size of vector G[w]
clear G[v] //removed all (bidirectional) edges that have u
for i = 0 ... |V|
if(G[i] is not empty) return false;
return true;
}
im trying this to lots of graphs (but their maximum size is 20 vertices) and this is taking a decade... is there any optimization I can do on this brute force so it run faster?

Related

Finding the number of strongly connected components

I have wrote this code for finding the number of SCC (strongly connected components):
#include <iostream>
#include <vector>
using namespace std;
int n , m;
vector<vector<int>>G(101) , GT(101);
void read()
{
//n = number of nodes , m = number of edges.
cin>>n>>m;
for (int i = 0 ; i < m ; i++)
{
int a , b;
cin>>a>>b;
G[a].push_back(b);
GT[b].push_back(a);
}
}
void DFS_G(int node , vector<int>&V)
{
V[node] = 1;
for (int x : G[node])
{
if (!V[x])
DFS_G(x , V);
}
}
void DFS_GT(int node , vector<int>&V)
{
V[node] = 1;
for (int x : GT[node])
{
if (!V[x])
DFS_GT(x , V);
}
}
int main()
{
//G-graph
//GT-reversed graph
int SCC = 0;
read();
vector<int>component(101 , 0);
vector<int>reachedG(101) , reachedGT(101);//will keep nodes reached from x in G and in GT
for (int i = 1 ; i <= n ; i++)
{
if (!component[i])
{
component[i] = 1;
for(int j = 1 ; j <= n ; j++)
{
reachedG[j] = reachedGT[j] = 0;
}
DFS_G(i , reachedG);
DFS_GT(i , reachedGT);
for (int j = 1 ; j <= n ; j++)
{
if (reachedG[j] == 1 && reachedGT[j] == 1)
{
component[j] = 1;
}
}
SCC++;
}
}
cout<<SCC;
return 0;
}
Let's say you are at node X.First we DFS from X , and find the nodes that we can reach from it.We mark them as reached in our reachedG vector.As you may know , by reversing a graph and then DFS from x , the nodes you will encounter are actually the nodes that can reach X.I keep them in reachedGT.So the intersection between these two vectors will actually be the SCC our node X is in.However , as I read on the internet, this isn't the best implementation of Kosaraju's algorithm.The more efficient one is this one from https://www.geeksforgeeks.org/strongly-connected-components/.
The steps are the following:
Create an empty stack ‘S’ and do DFS traversal of a graph. In DFS traversal, after calling recursive DFS for adjacent vertices of a vertex, push the vertex to stack. In the above graph, if we start DFS from vertex 0, we get vertices in stack as 1, 2, 4, 3, 0.
Reverse directions of all arcs to obtain the transpose graph.
One by one pop a vertex from S while S is not empty. Let the popped vertex be ‘v’. Take v as source and do DFS (call DFSUtil(v)). The DFS starting from v prints strongly connected component of v. In the above example, we process vertices in order 0, 3, 4, 2, 1 (One by one popped from stack).
I've spent quite some hours reading about it and I still don't understand the logic behind the stack with finishing times of our nodes.However , I think this approach is really similar to mine and that I'm missing something.I'd be happy if you helped me!
Let v be the last node to be finished. Every node that can reach v in the original graph (hence that v can reach in the transpose) is in v's strong component. Why? Suppose to the contrary that x is a node that can reach v, but v can't reach x. When we start x, the node v cannot be on the stack at the time because that would imply a path to x. We can't finish x until we've at least started every node that x can reach, so if v starts before x, it's already finished (because not on the stack), and if v starts after x, it finishes before x (because it's higher on the stack than x). Contradiction. This argument extends to a correctness proof.

Eigen: random binary vector with t 1s

I want to compute K*es where K is an Eigen matrix (dimension pxp) and es is a px1 random binary vector with 1s.
For example if p=5 and t=2 a possible es is [1,0,1,0,0]' or [0,0,1,1,0]' and so on...
How do I easily generate es with Eigen?
I came up with even a better solution, which is a combination of std::vector, Egien::Map and std::shuffle.
std::vector<int> esv(p,0);
std::fill_n(esv.begin(),t,1);
Eigen::Map<Eigen::VectorXi> es (esv.data(), esv.size());
std::random_device rd;
std::mt19937 g(rd());
std::shuffle(std::begin(esv), std::end(esv), g);
This solution is memory efficient (since Eigen::Map doesn't copy esv) and has the big advantage that if we want to permute es several times (like in this case), then we just need to repeat std::shuffle(std::begin(esv), std::end(esv), g);
Maybe I'm wrong, but this solution seems more elegant and efficient than the previous ones.
So you're using Eigen. I'm not sure what matrix type you're using, but I'll go off the class Eigen::MatrixXd.
What you need to do is:
Create a 1xp matrix that's all 0
Choose random spots to flip from 0 to 1 that are between 0-p, and make sure that spot is unique.
The following code should do the trick, although you could implement it other ways.
//Your p and t
int p = 5;
int t = 2;
//px1 matrix
MatrixXd es(1, p);
//Initialize the whole 1xp matrix
for (int i = 0; i < p; ++i)
es(1, i) = 0;
//Get a random position in the 1xp matrix from 0-p
for (int i = 0; i < t; ++i)
{
int randPos = rand() % p;
//If the position was already a 1 and not a 0, get a different random position
while (es(1, randPos) == 1)
randPos = rand() % p;
//Change the random position from a 0 to a 1
es(1, randPos) = 1;
}
When t is close to p, Ryan's method need to generate much more than t random numbers. To avoid this performance degrade, you could solve your original problem
find t different numbers from [0, p) that are uniformly distributed
by the following steps
generate t uniformly distributed random numbers idx[t] from [0, p-t+1)
sort these numbers idx[t]
idx[i]+i, i=0,...,t-1 are the result
The code:
VectorXi idx(t);
VectorXd es(p);
es.setConstant(0);
for(int i = 0; i < t; ++i) {
idx(i) = int(double(rand()) / RAND_MAX * (p-t+1));
}
std::sort(idx.data(), idx.data() + idx.size());
for(int i = 0; i < t; ++i) {
es(idx(i)+i) = 1.0;
}

Cut rectangle in minimum number of squares

I'm trying to solve the following problem:
A rectangular paper sheet of M*N is to be cut down into squares such that:
The paper is cut along a line that is parallel to one of the sides of the paper.
The paper is cut such that the resultant dimensions are always integers.
The process stops when the paper can't be cut any further.
What is the minimum number of paper pieces cut such that all are squares?
Limits: 1 <= N <= 100 and 1 <= M <= 100.
Example: Let N=1 and M=2, then answer is 2 as the minimum number of squares that can be cut is 2 (the paper is cut horizontally along the smaller side in the middle).
My code:
cin >> n >> m;
int N = min(n,m);
int M = max(n,m);
int ans = 0;
while (N != M) {
ans++;
int x = M - N;
int y = N;
M = max(x, y);
N = min(x, y);
}
if (N == M && M != 0)
ans++;
But I am not getting what's wrong with this approach as it's giving me a wrong answer.
I think both the DP and greedy solutions are not optimal. Here is the counterexample for the DP solution:
Consider the rectangle of size 13 X 11. DP solution gives 8 as the answer. But the optimal solution has only 6 squares.
This thread has many counter examples: https://mathoverflow.net/questions/116382/tiling-a-rectangle-with-the-smallest-number-of-squares
Also, have a look at this for correct solution: http://int-e.eu/~bf3/squares/
I'd write this as a dynamic (recursive) program.
Write a function which tries to split the rectangle at some position. Call the function recursively for both parts. Try all possible splits and take the one with the minimum result.
The base case would be when both sides are equal, i.e. the input is already a square, in which case the result is 1.
function min_squares(m, n):
// base case:
if m == n: return 1
// minimum number of squares if you split vertically:
min_ver := min { min_squares(m, i) + min_squares(m, n-i) | i ∈ [1, n/2] }
// minimum number of squares if you split horizontally:
min_hor := min { min_squares(i, n) + min_squares(m-i, n) | i ∈ [1, m/2] }
return min { min_hor, min_ver }
To improve performance, you can cache the recursive results:
function min_squares(m, n):
// base case:
if m == n: return 1
// check if we already cached this
if cache contains (m, n):
return cache(m, n)
// minimum number of squares if you split vertically:
min_ver := min { min_squares(m, i) + min_squares(m, n-i) | i ∈ [1, n/2] }
// minimum number of squares if you split horizontally:
min_hor := min { min_squares(i, n) + min_squares(m-i, n) | i ∈ [1, m/2] }
// put in cache and return
result := min { min_hor, min_ver }
cache(m, n) := result
return result
In a concrete C++ implementation, you could use int cache[100][100] for the cache data structure since your input size is limited. Put it as a static local variable, so it will automatically be initialized with zeroes. Then interpret 0 as "not cached" (as it can't be the result of any inputs).
Possible C++ implementation: http://ideone.com/HbiFOH
The greedy algorithm is not optimal. On a 6x5 rectangle, it uses a 5x5 square and 5 1x1 squares. The optimal solution uses 2 3x3 squares and 3 2x2 squares.
To get an optimal solution, use dynamic programming. The brute-force recursive solution tries all possible horizontal and vertical first cuts, recursively cutting the two pieces optimally. By caching (memoizing) the value of the function for each input, we get a polynomial-time dynamic program (O(m n max(m, n))).
This problem can be solved using dynamic programming.
Assuming we have a rectangle with width is N and height is M.
if (N == M), so it is a square and nothing need to be done.
Otherwise, we can divide the rectangle into two other smaller one (N - x, M) and (x,M), so it can be solved recursively.
Similarly, we can also divide it into (N , M - x) and (N, x)
Pseudo code:
int[][]dp;
boolean[][]check;
int cutNeeded(int n, int m)
if(n == m)
return 1;
if(check[n][m])
return dp[n][m];
check[n][m] = true;
int result = n*m;
for(int i = 1; i <= n/2; i++)
int tmp = cutNeeded(n - i, m) + cutNeeded(i,m);
result = min(tmp, result);
for(int i = 1; i <= m/2; i++)
int tmp = cutNeeded(n , m - i) + cutNeeded(n,i);
result = min(tmp, result);
return dp[n][m] = result;
Here is a greedy impl. As #David mentioned it is not optimal and is completely wrong some cases so dynamic approach is the best (with caching).
def greedy(m, n):
if m == n:
return 1
if m < n:
m, n = n, m
cuts = 0
while n:
cuts += m/n
m, n = n, m % n
return cuts
print greedy(2, 7)
Here is DP attempt in python
import sys
def cache(f):
db = {}
def wrap(*args):
key = str(args)
if key not in db:
db[key] = f(*args)
return db[key]
return wrap
#cache
def squares(m, n):
if m == n:
return 1
xcuts = sys.maxint
ycuts = sys.maxint
x, y = 1, 1
while x * 2 <= n:
xcuts = min(xcuts, squares(m, x) + squares(m, n - x))
x += 1
while y * 2 <= m:
ycuts = min(ycuts, squares(y, n) + squares(m - y, n))
y += 1
return min(xcuts, ycuts)
This is essentially classic integer or 0-1 knapsack problem that can be solved using greedy or dynamic programming approach. You may refer to: Solving the Integer Knapsack

Depth First Search on Adjacency Matrix

For this program, I am given a set of inputs that I need to store in an adjacency matrix. I've done this, so I have an adjacency matrix Matrix[11][11]. Now, using this matrix, I need to perform a depth first search and return the pi values.
I have the pseudocode for this, so I believe that I need two methods: DFS(graph) and DFS-VISIT(node). However, I'm having trouble actually implementing this. Can I do this using the adjacency matrix directly or do I somehow need to create a graph using the matrix? Any help with actually coding this would be appreciated.
DFS(G)
for each u ∈ V[G] do
color[u] = WHITE
∏[u] = NIL
time = 0
for each u ∈ V[G] do
if color[u] = WHITE then
DFS-VISIT(u)
DFS-VISIT(u)
color[u] = GRAY
time++
d[u] = time
for each v ∈ Adj[u] do
if color[v] = WHITE then
∏[v] = u
DFS-VISIT(v)
color[u] = BLACK
time++
f[u] = time
The pseudo-code you have there seems to assume an adjacency list.
Specifically this code: (indentation corresponding to code blocks assumed)
for each v ∈ Adj[u] do
if color[v] = white then
∏[v] = u
DFS-VISIT(v)
The difference is: with an adjacency matrix, all the vertices are there, and one typically uses 0/1 flags to indicate whether there's an edge between the current and target vertices.
So, you should loop through all vertices for that row in the adjacency matrix, and only do something when the flag is set to 1.
That part of the pseudo-code will look something like:
for v = 1 to n do // assuming 1-indexed
if color[v] = white && AdjMatrix[u][v] == 1 then
∏[v] = u
DFS-VISIT(v)
As far as I can tell, the rest of the psuedo-code should look identical.
Generally it is preferred to code DFS assuming graph to be represented as an adjacency list because the time complexity that results is O(|V| + |E|). But with adjacency matrix the time complexity becomes O(|V|*|V|). Below is an implementation of dfs assuming adjacency matrix representation:
#define WHITE 0
#define GRAY 1
#define BLACK 2
int time_;
vector<int> color(n, WHITE), par(n, 0), strt(n, 0), fin(n, 0);
vector<vector<int> > G(n, vector<int>(n, 0));
void dfs_visit(int);
void DFS(){
for(int i = 0; i < n; i++)
color[i] = 0, par[i] = -1;
time = 0;
for(int j = 0; j < n; i++)
if(color[j] == WHITE)
dfs_visit(j);
}
}
void dfs_visit(int u){
time_++;
strt[u] = time_;
color[u] = GRAY;
for(int v = 0; v < n && v++)
if(G[u][v] && color[v] == WHITE){
par[v] = u;
dfs_visit(v);
}
color[u] = BLACK;
time_++;
fin[u] = time_;
}
The par[] matrix calculates parent of each vertex and strt[] and fin[] matrices time stamp the vertices. Vertices are 0-based numbered.

Using Dijkstra's algorithm with an unordered_map graph

So this my current code, I will post the header declarations below...
// Using Dijkstra's
int Graph::closeness(string v1, string v2){
int edgesTaken = 0;
unordered_map<string, bool> visited;
unordered_map<string, int> distances;
string source = v1; // Starting node
while(source != v2 && !visited[source]){
// The node has been visited
visited[source] = 1;
// Set all initial distances to infinity
for(auto i = vertices.begin(); i != vertices.end(); i++){
distances[i->first] = INT_MAX;
}
// Consider all neighbors and calculate distances from the current node
// & store them in the distances map
for(int i = 0; i < vertices[source].edges.size(); i++){
string neighbor = vertices[source].edges[i].name;
distances[neighbor] = vertices[source].edges[i].weight;
}
// Find the neighbor with the least distance
int minDistance = INT_MAX;
string nodeWithMin;
for(auto i = distances.begin(); i != distances.end(); i++){
int currDistance = i->second;
if(currDistance < minDistance){
minDistance = currDistance;
nodeWithMin = i->first;
}
}
// There are no neighbors and the node hasn't been found yet
// then terminate the function and return -1. The nodes aren't connected
if(minDistance == INT_MAX)
return -1;
// Set source to the neighbor that has the shortest distance
source = nodeWithMin;
// Increment edgesTaken
edgesTaken++;
// clear the distances map to prepare for the next iteration
distances.clear();
}
return edgesTaken;
}
Declarations (This is an undirected graph) :
class Graph{
private:
// This holds the connected name and the corresponding we
struct EdgeInfo{
std::string name;
int weight;
EdgeInfo() { }
EdgeInfo(std::string n, int w) : name(n), weight(
};
// This will hold the data members of the vertices, inclu
struct VertexInfo{
float value;
std::vector<EdgeInfo> edges;
VertexInfo() { }
VertexInfo(float v) : value(v) { }
};
// A map is used so that the name is used as the index
std::unordered_map<std::string, VertexInfo> vertices;
NOTE: Please do not suggest that I change the header declarations, I am contributing to a project that has already had 8 other functions written and it's definitely too late to go back and change anything since every other function would then have to be rewritten
I'm currently getting incorrect output. The function is handling a 0 distance situation correctly however (If two vertices aren't connected then the function should return a -1). If the two nodes are the same vertex ex closeness("Boston", "Boston") then the function should return a 0.
Example graph
the closeness of the following two vertices on the left will be on the right:
Correct:
Trenton -> Philadelphia: 2
Binghamton -> San Francisco: -1
Boston -> Boston: 0
Palo Alto -> Boston: -1
Output of my function:
Trenton -> Philadelphia: 3
Binghamton -> San Francisco: -1
Boston -> Boston: 0
Palo Alto -> Boston: 3
I've tried to copy dijkstra's exactly how it is described, but I'm getting incorrect readings, I've been trying to figure this out for a while now -> Can anyone point me in the right direction?
This is most certainly not a real answer to the question (since I'm not pointing you in a direction regarding your implementation), but did you think about just using the Boost Graph library?
It boils down to writing a short Traits class for your graph structure (and thus it is not necessary to alter your graph definition/header) and is - at least for these fundamental algorithms - proven to be working stable and correctly.
I'd always suggest not to reinvent the wheel especially when it comes to graphs and numerics...
Your implementation is wrong, and it is only by chance you get "correct" results.
Lets do one example by hand. From Trenton to Philadelphia. I use the first letter of the cities as labels.
First iteration
visited = [(T, 1), (N, 0), (W, 0), (P, 0), (B, 0)]
minDistance = 3;
nodeWithMin = N;
edgesTaken = 1
second iteration
visited = [(T, 1), (N, 1), (W, 0), (P, 0), (B, 0)]
minDistance = 2;
nodeWithMin = W;
edgesTaken = 2
third iteration
visited = [(T, 1), (N, 1), (W, 1), (P, 0), (B, 0)]
minDistance = 2;
nodeWithMin = N;
edgesTaken = 3;
fourth iteration
N is already 1 so we stop. Can you see the errors?
Traditionally Dijkstras shortest path algorithm is implemented with a priority queue
dijkstra(graph, source)
weights is a map indexed by nodes with all weights = infinity
predecessor is a map indexed by nodes with all predecessors set to itself
unvisited is a priority queue containing all nodes
weights[source] = 0
unvisited.increase(source)
while unvisited is not empty
current = unvisited.pop();
for each neighbour to current
if weights[current] + edge_weight(current, neighbour) < weights[neighbour]
weights[neighbour] = weights[current] + + edge_weight(current, neighbour)
unvisited.increase(neighbour)
predecessors[neighbour] = current
return (weights, predecessors)
And you can get the path length by following the predecessors.
The problem with Palo Alto -> Boston seems to be that the algorithm takes the route Palo Alto -> San Fransisco -> Los Angeles -> San Fransisco (edgesTaken = 3) and then fails the while condition because San Fransisco's been visited already.