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));
Related
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
Is there a way to do weighted randomization in System Verilog based on runtime data. Say, I have a queue of integers and a queue of weights (unsigned integers) and wish to select a random integer from the first queue as per the weights in the second queue.
int data[$] = '{10, 20, 30};
uint_t weights[$] = '{100, 200, 300};
Any random construct expects the weights hardcoded as in
constraint range { Var dist { [0:1] := 50 , [2:7] := 50 }; }
But in my case, I need to pick an element from an unknown number of elements.
PS: Assume the number of elements and weights will be the same always.
Unfortunately, the dist constraint only lets you choose from a fixed number of values.
Two approaches I can think of are
Push each data value into a queue using the weight as a repetition count. In your example, you wind up with a queue of 600 values. Randomly pick an index into the queue. The selected element has the distribution you want. An example is posted here.
Create an array of ranges for each weight. For your example the array would be uint_t ranges[][2]'{{0,99},{100,299},{300,599}}. Then you could do the following in a constraint
index inside {[0:weights.sum()-1]};
foreach (data[ii])
index inside {[ranges[ii][0]:ranges[ii][1]} -> value == date[ii];
Say I am tossing a fair coin where 'tails' is assigned the value x = -1/2 and 'heads' is assigned x = 1/2.
I do this N times and I want to obtain the sum. This is what I have tried:
p = 0.5
N = 1e4
X(N,p)=(rand(N).<p)
I know this is incomplete but when I check (rand(N).<p) I see an array consisting of true, false. I interpret this as 'Tails' or 'Heads'. However, I don't know how to assign the values 1/2 and -1/2 to each of these elements in order for me to find the sum. If I simply use sum((rand(N).<p)) I do get an integer value, but I don't think this is the right way to do it because I haven't specified the values 1/2 and -1/2 anywhere.
Any help is greatly appreciated.
As indicated by the comments already, you want to do
sum(rand([-0.5, 0.5], N))
where N must be an integer (you wrote N=1e4, therefore typeof(N) == Float64 and rand won't work).
The documentation of rand (obtained by ?rand) describes what rand(S, N) does:
Pick a random element or array of random elements from the set of
values specified by S
Here, S can be an optional indexable collection, an array of values in your case (or a type like Int). So, above S = [-0.5, 0.5] and rand draws N random elements from this collection, which we can afterwards sum up.
Assigning specific values to a boolean array
Since this is the title of your question, and the answer above doesn't actually address this, let me comment on this as well.
You could do sum((rand(N).<p)-0.5), i.e. you shift all the ones to 0.5 and all the zeros to -0.5 to get the wanted result. Note that this is a general strategy: Let's say you want true to be a and false to be b, where a and b are numbers. You achieve this by (rand(N).<p)*(a-b) + b.
However, beyond being more "complicated", sum((rand(N).<p)-0.5) will allocate temporary arrays, first one of booleans, then one of numbers, the latter of which will eventually go into sum. Because of these unnecessary allocations this approach will be slower than the solution above.
I am looking for help with pseudo code (unless you are a user of Game Maker 8.0 by Mark Overmars and know the GML equivalent of what I need) for how to generate a list / array of unique combinations of a set of X number of integers which size is variable. It can be 1-5 or 1-1000.
For example:
IntegerList{1,2,3,4}
1,2
1,3
1,4
2,3
2,4
3,4
I feel like the math behind this is simple I just cant seem to wrap my head around it after checking multiple sources on how to do it in languages such as C++ and Java. Thanks everyone.
As there are not many details in the question, I assume:
Your input is a natural number n and the resulting array contains all natural numbers from 1 to n.
The expected output given by the combinations above, resembles a symmetric relation, i. e. in your case [1, 2] is considered the same as [2, 1].
Combinations [x, x] are excluded.
There are only combinations with 2 elements.
There is no List<> datatype or dynamic array, so the array length has to be known before creating the array.
The number of elements in your result is therefore the binomial coefficient m = n over 2 = n! / (2! * (n - 2)!) (which is 4! / (2! * (4 - 2)!) = 24 / 4 = 6 in your example) with ! being the factorial.
First, initializing the array with the first n natural numbers should be quite easy using the array element index. However, the index is a property of the array elements, so you don't need to initialize them in the first place.
You need 2 nested loops processing the array. The outer loop ranges i from 1 to n - 1, the inner loop ranges j from 2 to n. If your indexes start from 0 instead of 1, you have to take this into consideration for the loop limits. Now, you only need to fill your target array with the combinations [i, j]. To find the correct index in your target array, you should use a third counter variable, initialized with the first index and incremented at the end of the inner loop.
I agree, the math behind is not that hard and I think this explanation should suffice to develop the corresponding code yourself.
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;
}