我正在尝试使用系统Verilog约束求解器来解决以下问题陈述:
我们有N个球,每个球具有唯一的权重,因此需要将这些球分配到各个组中,以使每个组的权重不超过阈值(MAX_WEIGHT)。 现在我想找到所有可能的解决方案。我在SV中编写的代码如下:
`define NUM_BALLS 5
`define MAX_WEIGHT_BUCKET 100
class weight_distributor;
int ball_weight [`NUM_BALLS];
rand int unsigned solution_array[][];
constraint c_solve_bucket_problem
{
foreach(solution_array[i,j]) {
solution_array[i][j] inside {ball_weight};
//unique{solution_array[i][j]};
foreach(solution_array[ii,jj])
if(!((ii == i) & (j == jj))) solution_array[ii][jj] != solution_array[i][j];
}
foreach(solution_array[i,])
solution_array[i].sum() < `MAX_WEIGHT_BUCKET;
}
function new();
ball_weight = {10,20,30,40,50};
endfunction
function void post_randomize();
foreach(solution_array[i,j])
$display("solution_array[%0d][%0d] = %0d", i,j,solution_array[i][j]);
$display("solution_array size = %0d",solution_array.size);
endfunction
endclass
module top;
weight_distributor weight_distributor_o;
initial begin
weight_distributor_o = new();
void'(weight_distributor_o.randomize());
end
endmodule
我在这里面临的问题是我希望基于约束solution_array [i] .sum()<`MAX_WEIGHT_BUCKET;来随机确定数组的两个维度的大小。 。根据我对SV约束的理解,我相信在将值分配给数组之前,将解决数组的大小。
此外,我还想知道unique是否可以用于2维动态数组。
答案 0 :(得分:0)
您不能使用随机数生成器(RNG)来列举问题的所有可能解决方案。它不是为此而构建的。每次调用randomize()
时,RNG可以为您提供这些解决方案之一。但是,不能保证每次调用都会为您提供不同的解决方案。假设您有3个解决方案,S0, S1, S2
。求解器可以给您S1
,然后给S2
,然后给S1
,然后给S1
,然后给S0
,依此类推。如果您知道有多少个解决方案,您可以在看到所有内容后停止。通常,尽管如此,您事先并不知道这一点。
但是,RNG可以执行的操作是检查您提供的解决方案是否正确。如果遍历所有可能的解决方案,则只能过滤出正确的解决方案。在您的情况下,您有N个球,最多N个组。您可以先将每个球放在一个组中,然后尝试一下这是否是正确的解决方案。然后,您可以将2个球放在一个组中,将所有其他N-2放在一个组中。您可以将另外两个球放到一个组中,将所有其他球放到一个组中。您可以开始将2个球放入一组,将另外2个球放入一组,而将所有其他N-4放入一组。您可以继续执行此操作,直到将所有N个球放入同一组。我不太确定如何轻松列举所有解决方案。组合学可以为您提供帮助。在此方法的每个步骤中,您都可以检查某个球的布置是否满足约束条件:
// Array describing an arrangement of balls
// - the first dimension is the group
// - the second dimension is the index within the group
typedef unsigned int unsigned arrangement_t[][];
// Function that gives you the next arrangement to try out
function arrangement_t get_next_arrangement();
// ...
endfunction
arrangement = get_next_arrangement();
if (weight_distributor_o.randomize() with {
solution.size() == arrangement.size();
foreach (solution[i]) {
solution[i].size() == arrangement[i].size();
foreach (solution[i][j])
solution[i][j] == arrangement[i][j];
}
})
all_solutions.push_back(arrangement);
现在,让我们看一下weight_distributor
。我建议您在自己的约束中编写每个需求,因为这会使代码更具可读性。
您可以缩短使用双unique
运算符编写的唯一性约束:
class weight_distributor;
// ...
constraint unique_balls {
unique { solution_array };
}
endclass
您已经有一个约束,每个组最多只能有MAX_WEIGHT
:
class weight_distributor;
// ...
constraint max_weight_per_group {
foreach (solution_array[i])
solution_array[i].sum() < `MAX_WEIGHT_BUCKET;
}
endclass
由于解决了数组大小的问题,因此不可能编写约束来确保您可以使用简单的调用randomize()
计算出有效的解决方案。但是,如果要检查解决方案是否有效,则不需要此功能。这是由于在arrangement
和solution_array
之间对数组大小的限制。
答案 1 :(得分:0)
尝试一下!! ABC类; rand位[3:0] md_array [] []; //未知大小的多维数组
constraint c_md_array {
// First assign the size of the first dimension of md_array
md_array.size() == 2;
// Then for each sub-array in the first dimension do the following:
foreach (md_array[i]) {
// Randomize size of the sub-array to a value within the range
md_array[i].size() inside {[1:5]};
// Iterate over the second dimension
foreach (md_array[i][j]) {
// Assign constraints for values to the second dimension
md_array[i][j] inside {[1:10]};
}
}
}
endclass
模块tb;
initial begin
ABC abc = new;
abc.randomize();
$display ("md_array = %p", abc.md_array);
end
endmodule
https://www.chipverify.com/systemverilog/systemverilog-foreach-constraint