I have a sparse square matrix with the side 2*n.
eg.
1,0,0,1,0,1
0,1,1,1,0,1
1,0,0,0,1,1
0,0,1,1,0,0
1,1,1,0,0,0
0,0,0,1,1,0
And i need an efficient way to find a sub matrix with a size of n*n with the largest amount of 1s.
I have found various ways to do it but none faster then O(n^4). I've also found faster ways without the requirement that the sub matrix needs to be n*n.
EDIT:
The submatrix has to be contiguous,
Based on your claim of an O(n^4)-time algorithm, I'm assuming that the submatrix has to be contiguous, as otherwise the problem is NP-hard (it's harder than detecting a biclique). For an O(n^2)-time algorithm, it suffices to do O(n^2)-time preprocessing that enables O(1)-time queries of the form "given a, b, c, d, compute sum_{i=a}^b sum_{j=c}^d X[i,j]".
Given the array X[1..m,1..n], compute an array Y[0..m,0..n] as follows.
initialize Y to the zero array
for i from 1 to m
for j from 1 to n
Y[i,j] = Y[i-1,j] + X[i,j]
end
end
for i from 1 to m
for j from 1 to n
Y[i,j] = Y[i,j-1] + Y[i,j]
end
end
Now, Y[c,d] = sum_{i=1}^c sum_{j=1}^d X[i,j]. To compute sum_{i=a}^b sum_{j=c}^d X[i,j], use inclusion-exclusion: Y[c,d] - Y[a-1,d] - Y[c,b-1] + Y[a-1,b-1].
Related
Matrix Chain Multiplication has a dynamic programming solution where a recursive definition is used which works like this :
Problem : multiply i to j
Sub-problem : multiply i to k + multiply k+1 to j + multiplication cost
and this looks straight forward to memoize, due the repeating (i,j) sub-problems. But the following recursive definition which is bit different, I am facing difficulty memoizing it :
Can someone help memoizing this algo for matrix chain multiplication :
P is sequence of orders of matrices.
For eg, A(2,3)*B(3,4)*C(4,5), then P = {2,3,4,5}, i.e. order of ith matrix is P[i-1]*P[i]
also assumed P is 0-indexed.
Here I am multiplying adjacent matrices and recursing
Pseudocode :
chain_mul(P, n) {
if(n = 1) return 0
min_cost = inf
for( i = 1 to n-1) {
cost = P[i-1]*P[i]*P[i+1] + chain_mul(P-{P[i]}, n-1);
if(cost < min_cost) min_cost = cost
}
return min_cost
}
Here repeating sub-problem is structure of P, like I have shown below :
This cannot be memoized efficiently, because the argument P, iterates over all the subsets of the initial set P, so the memory required would be O(2^n).
The algoritms that can be memoized call the function specifying sections of the matrix chain, each section is characterized by two numbers, start and end index. The number of segments will be something like (n * (n + 1) / 2), and it is easy to implement a data structure to store and retrieve the results indexed by two numbers (e.g a matrix).
I am working on an interesting permutation cycle problem. We know any permutation of numbers is made up of disjoint cycles of numbers. For example let's say our original permutation is 12345. After one cycle the permutation becomes 14235. So 1 ==> 1, 2==>3, 3==>4, 4==2, and 5==>5. So our disjoint cycles, are
1, 234, and 5. Let's say we cycled like this 10^10 times. What is the end result? For example after one more cycle we get to 13425. I want to do this as efficiently as possible. Obviously we want to do modular arithmetic because there is a pattern, but how to write up this code in Java? Thanks
The key here is to use your modular arithmetic insight on each disjoint cycle independently.
For your example, you can get the result of 10^10 cycles
of the first disjoint cycle (1) trivially
of the second disjoint cycle (234) by cycling it (10^10)%3 = 1 times
of the third disjoint cycle (5) trivially
That just leaves finding the disjoint cycles, but that wasn't part of your question.
Basically, you can apply the same strategy as when implementing the calculation of a power a^n efficiently.
N can be decomposed as N = n[0] + n[1] 2 + n[2] 2^2 + ... + n[k] 2^k, with n[i] = 0 or 1
Applying the permutation P N times correspond to implement a permutation
P[N] = P[1]^n[0] x P[2]^n[1] x P[4]^n[2] x ... x P[2^k]^n[k] with P[1] = P
Where x corresponds to the composition of permutations.
Here, we use the conventions P[.]^0 = I (identity) and P[.]^1 = P[.]
The permutations P[2^i] can be calculated iteratively: P[2^i] = P[2^(i-1)] x P[2^(i-1)] as the n[i].
Complexity: O(p logN) where p is the size of the permutation
Given a prime number p, find a four integers such that p is equal to sum of square of those integers.
1 < p < 10^12.
If p is of form 8n + 1 or 8n + 5, then p can be written as sum of two squares. This can be solved in O(sqrt(p)*log(sqrt(p)). But for other cases,i.e. when p cannot be written as sum of two squares, than is very inefficient. So, it would be great if anyone can give some resource material which i can read to solve the problem.
Given your constraints, I think that you can do a smart brute force.
First, note that if p = a^2 + b^2 + c^2 + d^2, each of a, b, c, d have to be less than 10^6. So just loop over a from 0 to sqrt(p). Consider q = p - a^2. It is easy to check whether q can be written as the sum of three squares using Legendre's three-square theorem. Once you find a value of q that works, a is fixed and you can just worry about q.
Deal with q the same way. Loop over b from 0 to sqrt(q), and consider r = q - b^2. Fermat's two-square theorem tells you how to check whether r can be written as the sum of two squares. Though this check requires O(sqrt(r)) time again, in practice you should be able to quickly find a value of b that works.
After this, it should be straightforward to find a (c,d) pair that works for r.
Since the loops for finding a and b and (c,d) are not nested but come one after the other, the complexity should be low enough to work in your problem.
How can i write a pseudocode to calculate elements of matrix ?
The following algorithm finds the sum S of two n-by-n matrices A[0..n-1, 0..n-1] and B[0..n-1, 0..n-1].
To add two matrices, we add their corresponding elements. The resulting matrix S[0..n-1, 0..n-1] is an
n-by-n matrix with elements computed by the formula:
S[i, j] = A[i, j] + B[i, j]
Write the pseudocode for calculating the elements of matrix S.
ALGORITHM addMatrices(A[0..n-1,0..n-1], B[0..n-1, 0..n-1])
// Input: Two n-by-n matrices A and B
// Output: Matrix S = A + B
(i) What is the algorithm’s basic operation?
(ii) How many times is the basic operation executed?
(iii)What is the class O(…) the algorithm belongs to?
Algorithms basic operation is to access each element using two loops and add each element of 'A' matrix to each element of 'B' matrix designated by 'i' and 'j', and construct another matrix 'S' using it.
'S' denotes the sum matrix of 'A' and 'B' matrices.
The basic operation is executed n2 times, where 'n' is the order of the matrices.
For each i ∈ {0 , ... , n1-1} and each j ∈ {0 , ... , n2-1} where 'n1' and 'n2' are matrices order.
From 2nd part we denote the Big-O Notation complexity to be n2 or n1·n2 depending upon the order of the matrices.
While working on an image processing task I have come across the following problem: There are n points in the unit square with coordinates $x_i$ and $y_i$, each assigned with a positive or negative weight $w_i$. Find a rectangle such that the sum of all weights of those points lying within the rectangle is positive and maximal.
By defining a proper grid, the problem can be rephrased as finding a submatrix in an n-by-n matrix A whose sum of elements is maximal. This is also known as the "maximal subrectangle problem" and has been discussed on SO before. While a brute force approach has a run-time of O(n^5), there is a kind of tricky solution with a run-time of O(n^3). It utilizes a solution for the corresponding one-dimensional problem, called "maximal subarray problem", with an O(n) run-time.
I have implemented both algorithms in R and can solve 100s of points in a few seconds. But with thousands of points it will be much too slow, probably even when outsourcing the loops to some Fortran or C code.
Now look at the matrix A. When assuming (w/o loss of generality) that all points have different x- or y-coordinates, A has a special form: In each row and column of A there is exactly one non-zero element. For matrices with this special property I assume there should be an algorithm performing the task in O(n^2) time, or even better.
Here is an example with the optimal rectangle added:
set.seed(723)
N <- 50; w <- rnorm(N)
x <- runif(N); y <- runif(N)
clr <- ifelse (w >= 0, "blue", "red")
plot(x, y, pch = 20, col = clr, xlim = c(0, 1), ylim = c(0, 1))
rect(0.075, 0.45, 0.31, 0.95, border="gray")
You see that there can be red, ie. negative, points in the optimal rectangle. It also shows that it will not suffice to solve the one-dimensional cases for the x- and y-coordinates.
I will translate the standard solution into Fortran, but I would surely like to have a more efficient algorithm at hand.
These guys (found from the wiki page) claim to have a simpler sub-cubic solution for the 2-dimensional case. It may be the one you're already aware of.
See the accepted answer for "Maximum sum subrectangle in a sparse matrix". For an nxn matrix with m non-zero elements, the solution there takes O(nm log n) time. So, for you, since you have exactly n non-zero elements, this would give O(n^2 log n) time. Probably you'll be able to handle cases with n being 50 times larger or more, vs. the standard O(n^3) solution.
The best I can do is O(n^2 log n).
If we look at the n+1 choose 2 calls made by Kadane's 2D algorithm to Kadane's 1D algorithm on an input of your type, all but O(n) successive pairs are on 1D arrays that differ only in one element. I'm going to present a divide-and-conquer variant of Kadane's 1D; by caching the outcomes of each recursive call, only the O(log n) that involve the changed array element have to be recomputed, reducing the (amortized) running time of the inner loop from Theta(n) to Theta(log n).
def maxsubarray(arr, a, b):
# this function returns a 4-tuple
# element 0 is the max over intervals of the form [i, j)
# element 1 is the max over intervals of the form [i, b)
# element 2 is the max over intervals of the form [a, j)
# element 3 is the max over intervals of the form [a, b), i.e., sum(arr[a:b])
n = b - a
if n == 0:
return (0, 0, 0, 0)
elif n == 1:
x = arr[a]
y = max(x, 0)
return (y, y, y, x)
else:
m = a + n // 2
l = maxsubarray(arr, a, m)
r = maxsubarray(arr, m, b)
return (max(l[0], r[0], l[1] + r[2]),
max(r[1], l[1] + r[3]),
max(l[2], l[3] + r[2]),
l[3] + r[3])