Random sampling of SystemVerilog associative array - system-verilog

What is the best way to randomly sample an associative array? I have tried the following but the randomize method always fails.
std::randomize(idx) with {assoc_array.exists(idx);};
I guess I can call next method a random number of times starting from the first element of the associative array to achieve what's needed. However, is there a better way? Why wouldn't the constrained randomization above work?

The problem is when you have a function call in a constraint, the input arguments to the function are randomized first, and then the result is treated like a state variable when passed to the function. If the function returns false, the constraint fails, and idx is left unmodified. If it happens to choose an idx that does exist, then the constraint passes. I'm assuming the probability of picking an idx that exists is very low.
What I suggest is to put all of the indexes into an array, and then randomly select one of them
typedef bit [11:0] index_type; // or whatever your index type is
int assoc_array[index_type];
index_type idx, index_list[$];
...
index_list = assoc_array.find_index() with ('1);
std::randomize(idx) with {idx inside {index_list}};

Related

Matlab: Randomly select from "slowly varying" index set

I would like to find or implement a Matlab data structure that allows me to efficiently do the following three things:
Retrieve an element uniformly at random.
Add a new element.
Delete an element. (If it helps, this element was just "retrieved" out of the structure, so I can use both its location and its value to delete it).
Since I don't need duplicates, this structure is mathematically equivalent to a set. Also, my elements are always integers in the range 1 to 2500; it is not unusual for the set to be this entire range.
What is such a data structure? I've thought of using something like containers.Map or java.util.HashSet, but I don't know how to satisfy the first requirement in this case, because I don't know how to efficiently retrieve the nth key of such a structure. An ordinary array can achieve the first requirement of course, but it is a bad choice for the second and third requirements because of inefficient resizing.
For some context for why I'm looking to do this, in some current code I spent about 1/4 of the runtime doing:
find(x>0,Inf)
and then randomly retrieving an element from this vector. Yet this vector changes very little, and in a very predictable manner, in each iteration of my program. So I would prefer to carry around a data structure and update it as I go rather than recomputing it every time.
If you're familiar with Haskell, one way to implement the operations I'm looking to support would be
randomSelect set = fmap (\n -> elemAt n set) $ randomRIO (0,size set-1)
along with insert and delete, from Data.Set. But I have other reasons not to use Haskell in this project, and I don't know how to implement the backend of Data.Set myself.
Frequently, the best way to decrease time complexity is to increase space complexity. Given that your sets are going to be rather small, we can probably afford to use a little extra space.
To contain the set itself, you can use a preallocated array:
maxSize = 2500;
theSet = zeros(1, maxSize); % set elements
setCount = 0; % number of set elements
You can then have an auxiliary array to check for set membership:
isMember = zeros(1, maxSize);
To insert a new element newval into the set, add it to the end of theSet and increment the count (assuming there's room):
if ~isMember(newval)
assert(setCount < maxSize, 'Too many elements in set.');
theSet(++setCount) = newval;
isMember(newval) = 1;
else
% tried to add duplicate element... do something here
end
To delete an element by index delidx, swap the element to be deleted and the last element and decrement the count:
assert(delidx <= setCount, 'Tried to remove element beyond end of set.');
isMember(theSet(delidx)) = 0;
theSet(delidx) = theSet(setCount--);
Getting a random element of the set is then simple, just:
randidx = randi(setCount);
randelem = theSet(randidx);
All operations are O(1) and the only real disadvantage is that we have to carry along two arrays of size maxCount. Because of that you probably don't want to put these operations in functions as you'd end up creating new arrays on every function call. You'd be better off putting them inline or, better yet, wrapping them in a nice class.

"some_variable = []" type of statement in matlab

Hello and thanks for the help,
I have seen that you can make this statement:
some_variable = []
from what I see, this makes like a void variable for later use.
The thing is I want to make it an array (and that is the problem). I made this
some_variable(:) = []
but there is an error:
In an assignment A(:) = B, the number of elements in A and B must be the same
Thanks
Actually everything in MATLAB is an array, sometimes the arrays are just 1x1, but they are arrays nevertheless (unlike in C/C++ where you have int or int*).
So, when you do var=[] you initialize an empty array, an array of size 0*.
After that, its up to you to initialize it with whatever size you want. var=0 will initialize it as an array of 1x1 size, but you can go bigger, using zeros(size).
Adittionally, if you want to create empty variables of another class, just use <classname>.empty, such as in var=uint32.empty;
*Note that in MATLAB, an array is also infinite dimensional. It's not size 0, its 0x0x0x0x0x.....x0x0. If you want to prove this, try size(var,999999999999) in MATLAB.

MatLab: Error checking for integers in a row vector

I have used MatLab to write the following code for Horner's Algorithm
function [answer ] = Simple( a,x )
%Simple takes two arguments that are in order and returns the value of the
%polynomial p(x). Simple is called by typing Simple(a,x)
% a is a row vector
%x is the associated scalar value
n=length(a);
result=a(n);
for j=n-1:-1:1 %for loop working backwards through the vector a
result=x*result+a(j);
end
answer=result;
end
I now need to add an error check to ensure the caller uses integer values in the row vector a.
For previous integer checks I have used
if(n~=floor(n))
error(...
But this was for a single value, I am unsure how to do this check for each of the elements in a.
You've got (at least) two options.
1) Use any:
if (any(n ~= floor(n)))
error('Bummer. At least one wasn''t an integer.')
end
Or even more succinctly...
assert(all(n == floor(n)), 'Bummer. At least one wasn''t an integer.')
2) Use the much more capable validateattributes:
validateattributes(n, {'double'}, {'integer'})
This function can check for more than a dozen other things, too.
Same math will work, but is now checking each element. Try this:
if any(n~=floor(n))
error(...

What is the meaning of this command

capi = cell2mat(arrayfun(#(b) sum(resulti == b,1),nonzeros(unique(resulti)), 'UniformOutput', false))
why when I used that code, my code cannot run and there was command like the following command?
??? Array dimensions must match for binary array op.
All this can be found via Matlab's documentation, which should always be your first step!
Having said that, here's a breakdown of your command:
cell2mat: convert a cell array to a matrix according to some format you define
arrayfun: evaluate some function for all elements in an array. The function may be an anonymous function (e.g., #(b) sum(resulti == b,1))
sum: sum all the elements of a matrix in a particular direction. Direction 1: down the rows, direction 2: along the columns, etc.
nonzeros: form new array by removing all zeros from the input array. This will output a column vector, irrespective of the input's shape.
unique: return the input array with all duplicates of all values removed. The output will also be sorted.
Type help [command] or doc [command] for more information on all these commands (which I recommend you do!)
Now, combining these into your command:
A = nonzeros(unique(resulti))
will return all unique entries in a column vector, with any zero removed.
B = arrayfun(#(b)sum(resulti==b), A, 'UniformOutput', false)
will run the function #(b) sum(resulti == b,1) on all entries of the newly created column vector A, and collect them in a cell-array B (cell, because 'UniformOutput' is set to false). This function will simply compare each element of resulti against the running index b, and find the total count along the rows. Then, finally,
capi = cell2mat(B)
will convert the cell-array B back to a normal Matlab array.
The objective of this command seems to be to count the number of non-unique occurrences on each of the colums of resulti. As hinted at by #GuntherStruyf, this whole command seems a hacked-together, forced one-liner, rather than well-manageable, readable code. I would personally opt to break it over several lines, avoid arrayfun (slow) and instead use bsxfun or a for-loop (faster (yes, also the for-loop), better readable).
But that's a matter of opinion (which goes against popular opinion :)

Concatenate equivalent in MATLAB for a single value

I am trying to use MATLAB in order to generate a variable whose elements are either 0 or 1. I want to define this variable using some kind of concatenation (equivalent of Java string append) so that I can add as many 0's and 1's according to some upper limit.
I can only think of using a for loop to append values to an existing variable. Something like
variable=1;
for i=1:N
if ( i%2==0)
variable = variable.append('0')
else
variable = variable.append('1')
i=i+1;
end
Is there a better way to do this?
In MATLAB, you can almost always avoid a loop by treating arrays in a vectorized way.
The result of pseudo-code you provided can be obtained in a single line as:
variable = mod((1:N),2);
The above line generates a row vector [1,2,...,N] (with the code (1:N), use (1:N)' if you need a column vector) and the mod function (as most MATLAB functions) is applied to each element when it receives an array.
That's not valid Matlab code:
The % indicates the start of a comment, hence introducing a syntax error.
There is no append method (at least not for arrays).
Theres no need to increment the index in a for loop.
Aside of that it's a bad idea to have Matlab "grow" variables, as memory needs to be reallocated at each time, slowing it down considerably. The correct approach is:
variable=zeros(N,1);
for i=1:N
variable(i)=mod(i,2);
end
If you really do want to grow variables (some times it is inevitable) you can use this:
variable=[variable;1];
Use ; for appending rows, use , for appending columns (does the same as vertcat and horzcat). Use cat if you have more than 2 dimensions in your array.