Finding minimum cost in a binary matrix - algorithm

Consider a n * n binary matrix. Each cell of this matrix has at most 4 neighbors (if it exists). We call two cells of this matrix incompatible if they are neighbors and their values are not equal. We pay $b for each incompatible pair. Also we can change the value of the cell with paying $a.
The question is to find the minimum cost for this matrix.
I already used backtracking and found an algorithm of O(2 ^ (n * n)). Can someone help me find a more efficient algorithm?

This idea is due to Greig, Porteous, and Seheult. Treat the matrix as a capacitated directed graph with vertices corresponding to matrix entries and arcs from each vertex to its four neighbors, each with capacity b. Introduce two more vertices, a source and a sink, and arcs of capacity a: from the source to each vertex with a corresponding 0 entry, and to the sink from each vertex with a corresponding 1 entry. Find a minimum cut; the entries with value 0 after changes are the vertices on the source side of the cut, and the entries with value 1 after changes are the vertices on the sink side of the cut.
The cost of this cut is exactly your objective. Of the capacity-a from-source arcs, the ones crossing the cut correspond to changes from 0 to 1. Of the capacity-a to-sink arcs, the ones crossing the cut correspond to changes from 1 to 0. Of the capacity-b arcs, the ones crossing the cut correspond to those instances where there is an arc from a 0 to a 1.

I would suggest you to reformulate your backtracking in order to use dynamic programming to trimm the backtracking tree. Here is the logic I propose to design it:
When deciding if you want or not to change a cell, it doesn't really matter how you assigned the previous cells, it only matters the accumulated cost, so you can keep track for each cell, and each possible accumulated cost, what was the minimum result already found. This way whenever you find the same configuration again, you will have the answer saved.
So your dp matrix would be something like:
dp[top_bound][n][n];
And before doing backtracking you should do:
if(dp[acc_cost][this_i][this_j] != -1)
return dp[acc_cost][this_i][this_j];
// Perform your calculations
// ...
dp[acc_cost][this_i][this_j] = result;
return result;
Here I'm assuming -1 is an invalid value in the result, if not you just choose any invalid value and initialize your matrix to it. Since this matrix is of size n*n*top_bound, then a correctly implemented DP should solve the problem in O(n*n*top_bound).

Related

Finding mapping from set of start nodes to set of destination nodes in a grid

We are given a N x M size grid. Each cell represents height of cell.
You can travel to north/south/east/west of a cell if the neighbouring cell has a lower height.
All cells in first row are considered as set of start nodes.
All cells in last row are considered as set of destination nodes.
Find a binary matrix of size M x M where Matrix[i][j] = 1 iff I can start at cell (0, i) and reach to cell (N-1, j).
Here N, M <= 2000 and height of each cell is less than 10^9.
I have tried several approaches.
Observation: This grid is actually a DAG (Directed Acyclic Graph).
Approach #1: Do DFS from each cell in first row and find out list of cells you can reach at last row. This could take in worst case O(NxMxM) which is expensive.
Approach #2: Do DFS from each cell in first row and find out list of cells you can reach at last row, but do not re-do DFS for a cell if you have visited. Instead at each cell memorize the visitable cells in last row. Problem in this approach is it takes too much space: O(NxMxM).
Third idea is to think DSU (Disjoint Set Union) but it doesn't seem to be working. Spent couple of days thinking over this problem but cannot find a valid solution. TIA.
The grid is a DAG, but it also has the special property that no edges cross.
Let's classify each source vertex as either "live", if you can start there and reach some vertex in the last row, or "dead" if you cannot. It's not hard to classify the source vertices in O(NM) time.
Now we need only consider live sources. Since no edges can cross, for any vertex v, the live sources that can reach it must be contiguous. If there are sources a and b can reach v, then there is no way that a source between a and b could reach the end without joining a path that can reach v.
So, for each vertex, the sources that can reach it can be expressed as a range of sources (just 2 numbers), instead of a subset, which would be much bigger and more difficult to calculate.
If you process all of the vertices in order of descending height, then you can calculate the source range for each vertex from the source ranges of its neighbors in constant time. Each vertex can only be reached from its higher neighbors, and they will have been already calculated by the time you get to the vertex. Of course you must also consider that each source vertex is reachable from itself.
The time required for this algorithm is dominated by the sorting of vertices by height, and takes O(NM log NM) time.

Algorithm for finding optimal multiple partitionings based on some costs

I have a situation in which I need to find optimal split positions in an array based on some costs. The problem goes like this:
As input I have an array of events ordered by an integer timestamp and as output I want an array of indexes which split the input array into many parts. The output array needs to be optimal (more on this below).
struct e {
int Time;
// other values
}
Example Input: [e0, e1, e2, e3, e4, e5, ..., e10]
Example output: [0, 2, 6, 8] (the 0 at the start is always there)
Using the above examples I can use the split indices to partition the original array into 5 subarrays like so:
[ [], [e0, e1], [e2, e3, e4, e5], [e6, e7], [e8, e9, e10] ]
The cost of this example solution is the total cost of "distances" between the subarrays:
double distance(e[] arr1, e[] arr2) {
// return distance from arr1 to arr2, order matters so non-euclidean
}
total cost = distance([], [e0, e1]) + distance([e0, e1], [e2, e3, e4, e5]) + ...
At this point it is helpful to understand the actual problem.
The input array represents musical notes at some time (i.e. a MIDI file) and I want to split the MIDI file into optimal guitar fingerings. Hence each subarray of notes represents a chord (or a melody grouped together in a single fingering). The distance between two subarrays represents the difficulty of moving from one fingering pattern to another. The goal is to find the easiest (optimal) way to play a song on a guitar.
I have not yet proved it but to me this looks like an NP-Complete or NP-Hard problem. Therefore it could be helpful if I could reduce this to another known problem and use a known divide and conquer algorithm. Also, one could solve this with a more traditional search algorithm (A* ?). It could be efficient because we can filter out bad solutions much faster than in a regular graph (because the input is technically a complete graph since each fingering can be reached from any other fingering).
I'm not able to decide what the best approach would be so I am currently stuck. Any tips or ideas would be appreciated.
It's probably not NP-hard.
Form a graph whose nodes correspond one-to-one to (contiguous) subarrays. For each pair of nodes u, v where u's right boundary is v's left, add an arc from u to v whose length is determined by distance(). Create an artificial source with an outgoing arc to each node whose left boundary is the beginning. Create an artificial sink with an incoming arc from each node whose right boundary is the end.
Now we can find a shortest path from the source to the sink via the linear-time (in the size of the graph, so cubic in the parameter of interest) algorithm for directed acyclic graphs.
This is a bit late but I did solve this problem. I ended up using a slightly modified version of Dijkstra for this but any pathfinding algo could work. I tried A* as well but finding a good heuristic proved to be extremely difficult because of the non-euclidean nature of the problem.
The main changes to Dijkstra are that at some point I can already tell that some unvisited nodes cannot provide an optimal result. This speeds up the algorithm by a lot which is also one of the reasons I didn't opt for A*.
The algorithm essentially works like this:
search()
visited = set()
costs = map<node, double>()
// add initial node to costs
while costs is not empty:
node = node with minimum cost in costs
if current.Index == songEnd:
// backtrack from current to get fingering for the song
return solution
visited.add(node)
foreach neighbour of node:
if visited node:
continue
newCost = costs[node] + distance(node, neighbour)
add neighbour with newCost to costs
// we can remove nodes that have a higher cost but
// which have a lower index than our current node
// this is because every fingering position is reachable
// from any fingering positions
// therefore a higher cost node which is not as far as our current node
// cannot provide an optimal solution
remove unoptimal nodes from costs
remove node from costs
// if costs ends up empty then it is impossible to play this song
// on guitar (e.g. more than 6 notes played at the same time)
The magic of this algorithm happens in fetching the neighbours and calculating the distance between two nodes but those are irrelevant for this question.

Find a subset of k most distant point each other

I have a set of N points (in particular this point are binary string) and for each of them I have a discrete metric (the Hamming distance) such that given two points, i and j, Dij is the distance between the i-th and the j-th point.
I want to find a subset of k elements (with k < N of course) such that the distance between this k points is the maximum as possibile.
In other words what I want is to find a sort of "border points" that cover the maximum area in the space of the points.
If k = 2 the answer is trivial because I can try to search the two most distant element in the matrix of distances and these are the two points, but how I can generalize this question when k>2?
Any suggest? It's a NP-hard problem?
Thanks for the answer
One generalisation would be "find k points such that the minimum distance between any two of these k points is as large as possible".
Unfortunately, I think this is hard, because I think if you could do this efficiently you could find cliques efficiently. Suppose somebody gives you a matrix of distances and asks you to find a k-clique. Create another matrix with entries 1 where the original matrix had infinity, and entries 1000000 where the original matrix had any finite distance. Now a set of k points in the new matrix where the minimum distance between any two points in that set is 1000000 corresponds to a set of k points in the original matrix which were all connected to each other - a clique.
This construction does not take account of the fact that the points correspond to bit-vectors and the distance between them is the Hamming distance, but I think it can be extended to cope with this. To show that a program capable of solving the original problem can be used to find cliques I need to show that, given an adjacency matrix, I can construct a bit-vector for each point so that pairs of points connected in the graph, and so with 1 in the adjacency matrix, are at distance roughly A from each other, and pairs of points not connected in the graph are at distance B from each other, where A > B. Note that A could be quite close to B. In fact, the triangle inequality will force this to be the case. Once I have shown this, k points all at distance A from each other (and so with minimum distance A, and a sum of distances of k(k-1)A/2) will correspond to a clique, so a program finding such points will find cliques.
To do this I will use bit-vectors of length kn(n-1)/2, where k will grow with n, so the length of the bit-vectors could be as much as O(n^3). I can get away with this because this is still only polynomial in n. I will divide each bit-vector into n(n-1)/2 fields each of length k, where each field is responsible for representing the connection or lack of connection between two points. I claim that there is a set of bit-vectors of length k so that all of the distances between these k-long bit-vectors are roughly the same, except that two of them are closer together than the others. I also claim that there is a set of bit-vectors of length k so that all of the distances between them are roughly the same, except that two of them are further apart than the others. By choosing between these two different sets, and by allocating the nearer or further pair to the two points owning the current bit-field of the n(n-1)/2 fields within the bit-vector I can create a set of bit-vectors with the required pattern of distances.
I think these exist because I think there is a construction that creates such patterns with high probability. Create n random bit-vectors of length k. Any two such bit-vectors have an expected Hamming distance of k/2 with a variance of k/4 so a standard deviation of sqrt(k)/2. For large k we expect the different distances to be reasonably similar. To create within this set two points that are very close together, make one a copy of the other. To create two points that are very far apart, make one the not of the other (0s in one where the other has 1s and vice versa).
Given any two points their expected distance from each other will be (n(n-1)/2 - 1)k/2 + k (if they are supposed to be far apart) and (n(n-1)/2 -1)k/2 (if they are supposed to be close together) and I claim without proof that by making k large enough the expected difference will triumph over the random variability and I will get distances that are pretty much A and pretty much B as I require.
#mcdowella, I think that probably I don't explain very well my problem.
In my problem I have binary string and for each of them I can compute the distance to the other using the Hamming distance
In this way I have a distance matrix D that has a finite value in each element D(i,j).
I can see this distance matrix like a graph: infact, each row is a vertex in the graph and in the column I have the weight of the arc that connect the vertex Vi to the vertex Vj.
This graph, for the reason that I explain, is complete and it's a clique of itself.
For this reason, if i pick at random k vertex from the original graph I obtain a subgraph that is also complete.
From all the possible subgraph with order k I want to choose the best one.
What is the best one? Is a graph such that the distance between the vertex as much large but also much uniform as possible.
Suppose that I have two vertex v1 and v2 in my subgraph and that their distance is 25, and I have three other vertex v3, v4, v5, such that
d(v1, v3) = 24, d(v1, v4) = 7, d(v2, v3) = 5, d(v2, v4) = 22, d(v1, v5) = 14, d(v1, v5) = 14
With these distance I have that v3 is too far from v1 but is very near to v2, and the opposite situation for v4 that is too far from v2 but is near to v1.
Instead I prefer to add the vertex v5 to my subgraph because it is distant to the other two in a more uniform way.
I hope that now my problem is clear.
You think that your formulation is already correct?
I have claimed that the problem of finding k points such that the minimum distance between these points, or the sum of the distances between these points, is as large as possible is NP-complete, so there is no polynomial time exact answer. This suggests that we should look for some sort of heuristic solution, so here is one, based on an idea for clustering. I will describe it for maximising the total distance. I think it can be made to work for maximising the minimum distance as well, and perhaps for other goals.
Pick k arbitrary points and note down, for each point, the sum of the distances to the other points. For each other point in the data, look at the sum of the distances to the k chosen points and see if replacing any of the chosen points with that point would increase the sum. If so, replace whichever point increases the sum most and continue. Keep trying until none of the points can be used to increase the sum. This is only a local optimum, so repeat with another set of k arbitrary/random points in the hope of finding a better one until you get fed up.
This inherits from its clustering forebear the following property, which might at least be useful for testing: if the points can be divided into k classes such that the distance between any two points in the same class is always less than the distance between any two points in different classes then, when you have found k points where no local improvement is possible, these k points should all be from different classes (because if not, swapping out one of a pair of points from the same class would increase the sum of distances between them).
This problem is known as the MaxMin Diversity Problem (MMDP). It is known to be NP-hard. However, there are algorithms for giving good approximate solutions in reasonable time, such as this one.
I'm answering this question years after it was asked because I was looking for algorithms to solve the same problem, and had trouble even finding out what to call it.

Number of closed regions created by a path

Given a path P described by a list of positions in the xy-plane that are each connected by edges, compute the least number of edges that have to be removed from P such that P does not close off any regions in the xy-plane (i.e., it should be possible to go from any point to any other point). Every position will have integer coordinates, and each position will be one unit left, right, up, or down from the previous one.
For example, if P = {[0,0], [0,1], [1,1], [1,0], [0,0]}, then the path is a square starting and ending at (0,0). Any 1 of the 4 edges of the square could be removed, so the answer is 1.
Note that the same edge can be drawn twice. That is, if P = {[0,0], [0,1], [1,1], [1,0], [0,0], [0,1], [1,1], [1,0], [0,0]}, the answer would be 2, because now each side of the square has 2 edges, so at least 2 edges would have to be removed to "free" the square.
I've tried a naive approach where if any position is visited twice, there could be an enclosed region (not always, but my program relies on this assumption), so I add 1 to the minimum number of edges removed. In general if a vertex is visited N times I add N-1 to the number of edges removed. However, if, for example, P = {[0,0], [0,1], [0,0]}, there is no enclosed region whereas my program would think there is. Another case of where it breaks down: if P = {[0,0], [0,1], [1,1], [1,0], [0,0], [1,0]}, my program would output 2 (since (0,0) and (0,1) are each visited twice), whereas the correct answer is 1, since we can just remove any of the other three sides of the square.
It seems that there are two primary subtasks to solve this problem: first, given the path, figure out which positions are enclosed (i.e., figure out the regions that the path splits the graph into); second, use knowledge of the regions to identify which edges must be removed to prevent enclosures.
Any hints, pseudocode, or code would be appreciated.
Source: Princeton's advanced undergraduate class on algorithms.
Here are a few ideas that might help. I'm going to assume that you have n points.
You could first insert all of the edges in a set S so that duplicate edges are removed:
for(int i = 0; i < n-1; i++)
S.insert( {min(p[i], p[i+1), max(p[i], p[i+1])} );
Now iterate over the edges again and build a graph. Then find the longest simple path in this graph.
The resulting graph is bipartite (if a cycle exists it must have even length). This piece of information might help as well.
You could use a flood-fill algorithm to find the contiguous regions of the plane created by the path. One of these regions is infinite but it's easy to compute the perimeter with a scanline sweep, and that will limit the total size to be no worse than quadratic in the length of the path. If the path length is less than 1,000 then quadratic is acceptable. (Edit: I later realized that since it is only necessary to identify the regions adjacent to edges of the line, you can do this computation by sorting the segments and then applying a scanline sweep, resulting in O(n log n) time complexity.)
Every edge in the path is between two regions (or is irrelevant because the squares on either side are the same region). For the relevant edges, you can count repetitions and then find the minimum cost boundary between any pair of adjacent regions. All that is linear once you've identified the region id of each square.
Now you have a weighted graph. Construct a minimum spanning tree. That should be precisely the minimum collection of edges which need to be removed.
There may well be a cleverer solution. The flood-fill strikes me as brute-force and naive, but it's the best I can do in ten minutes.
Good luck.

Algorithm for classification of vertices in a graph based on their weight

I have the following complete weighted graph, where each weight represents the probability of a vertice belonging to the same category as the next. I know a priori the category for which some of the vertices belong to; how would I be able to classify every other vertice?
In a more detailed manner I can describe the problem as following; From all the vertices N and clusters C, we have a set where we know for sure the specific cluster which a node belongs: P(v_n|C_n)=1. From the graph given we also know for each node, the probability of every other belonging to the same cluster as it: P(v_n1∩C_n2). From this, how can we estimate the cluster for every other node?
Let w_i be a vector where w_i[j] is the probability of node j, being in the cluser, at iteration i.
We define w_i:
w_0[j] = 1 j is given node in the class
0 otherwise
w_{i}[j] = P(j | w_{i-1})
Where: P(j | w_{i-1}) is the probability j being in the cluster, assuming we know the probabilities for each other node k to be in it, as w_{i-1}[k].
We can calculate the above probability:
P(j | w_{i-1}) = 1- (1- w_{i-1}[0]*c(0,j))*(1- w_{i-1}[1]*c(1,j))*...*(1- w_{i-1}[n-1]*c(n-1,j))
in here:
w_{i-1} is the output of last iteration.
c(x,y) is the weight of edge (x,y)
c(x,x) = 1
Repeat until convergence, and in the converged vector (let it be w), the probability of j being in the cluster is w[j]
Explanation for the probability function:
In order for a node NOT to be in the set, it needs all the other nodes will "decide" not to share it.
So, the probability for that happening is:
(1- w_{i-1}[0]*c(0,j))*(1- w_{i-1}[1]*c(1,j))*...*(1- w_{i-1}[n-1]*c(n-1,j))
^ ^ ^
node 0 doesn't share node 1 doesn't share node n-1 doesn't share
In order to be in the class, at least one node need to "share", so the probability for that happening is the complemantory, which is the formula we derived for P(j | w_{i-1})
You should start from the definition of the result. How should you show the probabilities of belonging?
The result, IMHO, should be a set of categories and a table: rows for vertices and columns for categories, and in the cells there will be possibilities of belonging of that vertice to this category.
Your graph can set some probabilities of belonging only if you already have some start known probabilities. I.e, that table would be already partly filled.
While filling the table according to the start values and weights of edges we would surely come to the situation, when we are getting different probabilities in the cells, coming into it by different ways. One more point should be set: can we change the start values in the table or they are set hardly? The same question for the weights of the edges.
Now the task is partly defined, and the part is very, very small. You even don't know the number of categories!
After you set all these rules and numbers, all is quite trivial - use The Gauss Method of Lesser Squares. As for iterative way, be careful - you don't know beforehand if the solution is stable or if it exists. If not, the iteration won't converge, and the whole that piece of code you wrote for it is for nothing. And by Gauss method you are getting a set of linear equations, and the standard algorithms are written to solve it for all cases. And at the end you have not only the solution, but the possible mistake for every final value.

Resources