I would like to randomize an array of numbers with the following given constraints:
- all numbers are inside [1:7]
- array average is 4.882
- “triangular shaped” distribution around the array average. i.e. majority of the numbers (>90%) should be in the range [$floor(avg):$ceil(avg)] (=[4:5]), and then with lower probability the numbers {3,6}, and then with the least probability (~1%) the numbers {1,2,7}
I’ve tried the following code:
class credit_flow_data #(int size = 1000);
int credit_prob;
rand int credit_high_duration_arr[size];
longint credit_high_duration_arr_desired_sum;
real credit_high_duration_desired_avg;
real credit_low_duration_desired_avg;
function new(int credit_prob, real credit_low_duration_desired_avg);
this.credit_prob = credit_prob;
this.credit_low_duration_desired_avg = credit_low_duration_desired_avg;
calc_credit_high_duration_desired_avg();
this.credit_high_duration_arr_desired_sum = longint'(this.size*this.credit_high_duration_desired_avg);
endfunction
function void calc_credit_high_duration_desired_avg();
real credit_prob_normalized = real'(this.credit_prob)/100.0;
if (credit_prob_normalized == 0 || credit_prob_normalized == 1) begin
this.credit_high_duration_desired_avg = credit_prob_normalized;
end
else begin
this.credit_high_duration_desired_avg = credit_prob_normalized/(1-credit_prob_normalized)*this.credit_low_duration_desired_avg;
end
$display("credit_high_duration_desired_avg = %0f", credit_high_duration_desired_avg);
endfunction: calc_credit_high_duration_desired_avg
constraint credit_high_duration_arr_c {
if (this.credit_prob == 0 || this.credit_prob == 100) {
foreach (credit_high_duration_arr[i]) {
credit_high_duration_arr[i] == this.credit_prob/100;
}
}
else {
foreach (credit_high_duration_arr[i]) {
credit_high_duration_arr[i] inside {[1:7]};
credit_high_duration_arr[i] dist {4:=950, 5:=950, [1:2]:/5, 3:=50, 6:=50, 7:=5};
}
credit_high_duration_arr.sum() with (int'(item)) == credit_high_duration_arr_desired_sum;
}
}
endclass
module tb;
credit_flow_data #(1000) data;
int credit_prob;
initial begin
credit_prob = 83;
data = new(credit_prob, 1);
data.randomize();
for (int i=0; i<data.size; i++) begin
$display("%0d", data.credit_high_duration_arr[i]);
end
end
endmodule
The avg is as expected - 4.882, but oddly the probability of 7’s is too high - 154/1000=15.4% !
In addition, most of the 7’s are located at the end of the array (sequence of 7’s), and it’s less desired. I would like a more shuffled like behavior (i.e. the 7’s should be spread throughout the array).
Any suggestions?
Other solutions to the problems also welcome :)