Finding if binary matrix exists given the row and column sums - math

How to find out if it is possible to contruct a binary matrix with given row and column sums.
Input :
The first row of input contains two numbers 1≤m,n≤1000, the number of rows and columns of the matrix. The next row contains m numbers 0≤ri≤n – the sum of each row in the matrix. The third row contains n numbers 0≤cj≤m – the sum of each column in the matrix.
Output:
Output “YES” if there exists an m-by-n matrix A, with each element either being 0 or 1. Else "NO".
I tried reading about Tomography algorithms but could not figure out an answer as all the papers related to Tomography algorithm is very complicated.
Can someone please help me..

I've successfully implemented randomly generating such matrices for R using a modeling based on network flow. I intend to write up those ideas one day, but haven't found the time yet. Reasearching for that, I read in Randomization of Presence–absence Matrices: Comments and New Algorithms by Miklós and Podani:
The Havel-Hakimi theorem (Havel 1955, Hakimi 1962) states that there exists a matrix Xn,m of 0’s and 1’s with row totals a0=(a1, a2,… , an) and column totals b0=(b1, b2,… , bm) such that bi ≥ bi+1 for every 0 < i < m if and only if another matrix Xn−1,m of 0’s and 1’s with row totals a1=(a2, a3,… , an) and column totals b1=(b1−1, b2−1,… ,ba1−1, ba1+1,… , bm) also exists.
I guess that should be the best method to recursively decide your question.
Phrased in my own words: Choose any row, remove it from the list of totals. Call that removed number k. Also subtract one from the k columns with larges sums. You obtain a description of a smaller matrix, and recurse. If at any point you don't have k columns with non-zero sums, then no such matrix can exist. Otherwise you can recursively build a matching matrix using the reverse process: take the matrix returned by the recursive call, then add one more row with k ones, placed in the columns from whose counts you originally subtracted one.
Implementation
bool satisfiable(std::vector<int> a, std::vector<int> b) {
while (!a.empty()) {
std::sort(b.begin(), b.end(), std::greater<int>());
int k = a.back();
a.pop_back();
if (k > b.size()) return false;
if (k == 0) continue;
if (b[k - 1] == 0) return false;
for (int i = 0; i < k; i++)
b[i]--;
}
for (std::vector<int>::iterator i = b.begin(); i != b.end(); i++)
if (*i != 0)
return false;
return true;
}

Related

for and if cicle operations

Hi¡ I have a doubt and I hope someone can help me please, I have a dataframe in R and it makes a double cicle for and an if, the data frame has some values and then if the condition is True, it makes some operations, the problem is I can't understand neither the cicle and the operation the code makes under the condition.
I reply the code I have in a simpler one but the idea is the same. And if someone can explain me the whole operation please.
w<-c(2,5,4,3,5,6,8,2,4,6,8)
x<-c(2,5,6,7,1,1,4,9,8,8,2)
y<-c(2,5,6,3,2,4,5,6,7,3,5)
z<-c(2,5,4,5,6,3,2,5,6,4,6)
letras<-data.frame(w,x,y,z)
l=1
o=1
v=nrow(letras)
letras$op1<-c(1)
letras$op2<-c(0)
for (l in 1:v) {
for (o in 1:v) {
if(letras$x[o]==letras$y[l] & letras$z[l]==letras$z[o] & letras$w[l]){
letras$op1<-letras$op1+1
letras$op2<-letras$x*letras$y
}
}
}
The result is the following:
Thanks¡¡¡¡¡
This segment of code is storing values into vectors labeled w,x,y,z.
w<-c(2,5,4,3,5,6,8,2,4,6,8)
x<-c(2,5,6,7,1,1,4,9,8,8,2)
y<-c(2,5,6,3,2,4,5,6,7,3,5)
z<-c(2,5,4,5,6,3,2,5,6,4,6)
It then transforms the 4 vectors into a data frame
letras<-data.frame(w,x,y,z)
This bit of code isn't doing anything as far as I can tell.
l=1 #???
o=1 #???
This counts how many rows is in the letras data frame and stores to v, in this case 11 rows.
v=nrow(letras)
This creates new columns in letras dataframe with all ones in op1 and all zeros in op2
letras$op1<-c(1)
letras$op2<-c(0)
Here each for loop is acting as a counter, and will run the code beneath it iteratively from 1 to v (11), so 11 iterations. Each iteration the value of l will increase by 1. So first iteration l = 1, second l=2... etc.
for (l in 1:v) {
You then have a second counter, which is running within the first counter. So this will iterate over 1 to 11, exactly the same way as above. But the difference is, this counter will need to complete it's 1 to 11 cycle before the top level counter can move onto the next number. So o will effectively cycle from 1 to 11, for each 1 count of 1l. So with the two together, the inside for loop will count from 1 to 11, 11 times.
for (o in 1:v) {
You then have a logical statement which will run the code beneath if the column x and column y values are the same. Remember they will be calling different index values so it could be 1st x value vs the 2nd y value. There is an AND statement so it also needs the two z position values to be equal. and the last part letras$w[l] is always true in this particular example, so could possibly be removed.
if(letras$x[o]==letras$y[l] & letras$z[l]==letras$z[o] & letras$w[l]){
Lastly, is the bit that happens if the above statement is true.
op1 get's 1 added (remember this was starting from 1 anyway), and op2 multiplies x*y columns together. This multiplication is perhaps a little bit inefficient, because x and y do not change, so the answer will calculate the same result each time the the if statement evaluates TRUE.
letras$op1<-letras$op1+1
letras$op2<-letras$x*letras$y
}
}
}
Hope this helps.

How many sum of repeatable combinations of length N?

How many sum of repeatable combinations of length N ?
Like [1,3,5,10], N = 4.
And there gonna be
[1,1,1,1] -> sum is 4
[1,1,1,3] -> sum is 6
...
[10,10,10,10] -> sum is 40
I perform a backtracking algo. by python3
res = set()
n = 4
def backtrack(k, path):
if len(path) == n:
res.add(sum(path))
return
backtrack(k+1, path+[1])
backtrack(k+1, path+[3])
backtrack(k+1, path+[5])
backtrack(k+1, path+[10])
return
backtrack(0, list())
Is there has more efficient solution?
If n elements order be not important, then your code is wrong
for example [1,1,2,2] ~ [1,2,1,2]
You can create a new list and repeat each element of the original n times. then the question is how many ways we can select n item from new list which can be calculated easily
further more if you want the result set of all the sums i think there's no better way than iterating in all situations.
O(n*len(list)*numberofdistinctsums) approach.
We have two sets containing current possible sums for odd and even steps.
We calculate new sums formed with i+1 summands from previous step sums (with i summands).
For example, after two rounds we have all possible sums of two summands. Getting sum 8 from previous set, we put sums of three summands 8+1, 8+3,8+5, 8+10 into new set and so on.
a = [1,3,5,10]
n = 4
sums = [set(a), set()]
for i in range(1, n):
sums[i%2].clear
for j in sums[(i+1)%2]:
for x in a:
sums[i%2].add(j + x)
print(len(sums[(n-1)%2]))

Recursive method to finding the k element subsets of a set with n elements

Consider the problem of finding the k element subsets of a set with n elements. Write a recursive function that takes an array of integers representing the set, the number of integers in the set (n), and the required subset size (k) as input, and displays all subsets with k elements on the screen. You may assume that the elements in the array have unique values. For example, if the array (set) contains the elements [ 8 2 6 7 ], n is 4, and k is 2, then the output is 82 86 87 26 27 67.
Can you help me with this, at least tell what way should I follow?
The type of thing you're talking about is a **combination&&.
There's a recursive definition of the calculation tucked in the middle of the Wikipedia page.
$$\binom{n}{k}=\binom{n-1}{k-1}+\binom{n-1}{k}$$
Figuring out what your base cases are might be tricky, but I think everything you need is there.
I would've right something like this:
subset ( numbers, n, k, index)
{
if (index < n) // end for the recursion. passed through all elements
{
if (k == 0) // end for the recursion. no more elements needed
print ' '
else
{
print numbers[index]
subset(numbers, n, k-1, index+1) // uses the number in the current index
subset(numbers, n, k, index+1) // doesn't use the number in the current index
}
}
call subset(numbers, n, k, 0) to start
notice that because order doesn't play a role in sets, its enough to pass over the elements in one direction

Sum 2D array in constraints in system verilog

I'm trying to create constraint using a 2d array filled with 1's and 0's.
I want every row to have a total sum of either 0,1,2,4 and every column sums to 1. Moreover, I want the entire sum of the matrix to be equal to 8 (which worked using sum function).
I tried using the function .sum() to constraint of every row and column to the value I demanded, but I keep getting syntax error. What am I doing wrong?
rand bit MAT[8][8];
constraint range {
MAT.sum() with (32' (item)) == 8;
foreach (MAT[j]){
foreach(MAT[j][i]){
MAT[j][].sum() with (32' (item)) == 1;
MAT[][i].sum() with (32' (item)) inside {0,1,2,4};
}
}
Section 7.12.3 Array reduction methods of the IEEE 1800-2012 standard states that
[array] reduction methods may be applied to any unpacked array of integral values to reduce the array to a
single value.
While MAT[0].sum() or MAT[1].sum() is allowed (apply sum on line 0 and 1 respectively of MAT), MAT.sum() is not. A line in MAT is an array of bit and bit is an integral type, but MAT is an array of unpacked array of bit which is not an integral type.
Also, it's not possible to select a single column from an array. You can only slice row-wise. This is a bit trickier to implement, but doable.
Let's look at each constraint. First, constraining the sum of each row is easily done with the sum() function:
constraint sum_on_row {
foreach (MAT[i])
MAT[i].sum() with (32'(item)) inside { 0, 1, 2, 4 };
}
To constraint the sum on a column you'll need to transpose the array (rows become columns, columns become rows) and constrain that. First, let's define the transpose of MAT:
rand bit MAT_transp[8][8];
constraint construct_MAT_transp {
foreach (MAT[i,j])
MAT_transp[j][i] == MAT[i][j];
}
We allocate another array and keep its contents in sync with those of MAT. Any constraints on MAT_transp will indirectly affect MAT. As before, we can constrain the rows of MAT_transp, which will effectively constrain the columns of MAT:
constraint sum_on_col {
foreach (MAT_transp[i])
MAT_transp[i].sum() with (32'(item)) == 1;
}
And lastly, you want the sum of all elements in the array to be 8. This is the trickiest to do. While we can't constrain the array sum directly, we can split the problem into two parts. First, we can compute the sum for each row in MAT and store them all in an array:
rand int unsigned row_sums[8];
constraint compute_row_sums {
foreach (row_sums[i])
row_sums[i] == MAT[i].sum() with (32'(item));
}
Now that we have the sum on each row, it's easy to constrain the sum of the entire array by constraining the sum of all row sums:
constraint sum_of_matrix {
row_sums.sum() == 8;
}
The cool thing is that with this one problem we've covered a lot of the usual "tricks" we can apply when constraining arrays. You can find more array constraint idioms in an old post I wrote.
Actually, array2d.sum() works with VCS.
For sum along 2nd index:
Instead of
MAT[j][].sum() with (32'(item))
Use
MAT[j].sum() with (32'(item))
For sum along 1st index:
Instead of
MAT[][i].sum() with (32'(item))
Use
MAT.sum() with (32'(item[i]))
Note: For sum along any index of a multi-dimensional array, specify the higher dimension indices and then reduce the sub array obtained, using with clause for lower dimension indices.
Example:
bit bit_array [n0][n1][n2][n3][n4];
int sum_0 = bit_array.sum() with (int'(item[i1][i2][i3][i4]));
int sum_1 = bit_array[i0].sum() with (int'(item[i2][i3][i4]));
int sum_2 = bit_array[i0][i1].sum() with (int'(item[i3][i4]));
int sum_3 = bit_array[i0][i1][i2].sum() with (int'(item[i4]));
int sum_4 = bit_array[i0][i1][i2][i3].sum() with (int'(item));

NTh square free semi prime

I am trying to find the nth( n <= 2000000) square free semi prime. I have the following code to do so.
int k = 0;
for(int i = 0; i <= 1000; i++)
{
for(int j = i +1 ; j <= 2500; j++ )
{
semiprimes[k++] = (primes[i]*primes[j]);
}
}
sort(semiprimes,semiprimes+k);
primes[] is a list of primes.
My problem is, i get different values for n = 2000000, with different limits on the for loops. Could someone tell a way to correctly calculate these limits?
Thanks in advance..
You want to calculate the nth first semi-prime square-free numbers. "first" means that you have to generate all of them under a certain value. Your method consist of generating a lot of those numbers, sort them and extract the nth first values.
This can be a good approach but you must have all the numbers generated. Having two different limits in your nested loops is a good way to miss some of them (in your example, you are not calculating primes[1001]*primes[1002] which should be in semiprimes).
To avoid this problem, you have to compute all the semi-prime numbers in a square, say [1,L]*[1,L], where L is your limit for both loops.
To determine L, all you need is it to count.
Let N be the number of semi-prime square-free numbers under primes[L-1]*primes[L-1].
N = (L * L - L) / 2
L*L is the total number of pairwise multiplications. L is the number of squares. This has two be divided by two to get the right number (because primes[i]*primes[j] = primes[j]*primes[i]).
You want to pick L such that n<=N. So for n = 2000000 :
int L = 2001, k = 0;
for(int i = 0; i < L; i++)
{
for(int j = i+1 ; j < L; j++ )
{
semiprimes[k++] = (primes[i]*primes[j]);
}
}
sort(semiprimes,semiprimes+k);
I don't believe an approach that works by computing all semiprimes inside a box will work in any reasonable amount of time. Say we graph the factors (p,q) of the first 2 million semiprimes. To make the graph more symmetric, let's plot a point for both (p,q) and (q,p). The graph does not form a nice rectangular region, but instead looks more like the hyperbola y=1/x. This hyperbola stretches out quite far, and iterating over the entire rectangle containing these will be a lot of wasted computation.
You may want to consider first solving the problem "how many semiprimes are there below N?" and then using a binary search. Each query can be done in about sqrt(N) steps (hint: binary search strikes again). You will need a fairly large table of primes, certainly at least up to 1 million, probably more. Although this can be trimmed down by an arbitrarily large constant factor with some precomputation.

Resources