Вы не можете использовать генератор случайных чисел (RNG), чтобы перечислить все возможные решения вашей проблемы.Это не построено для этого.RNG может предоставить вам одно из этих решений при каждом вызове randomize()
.Не гарантируется, однако, что это дает вам другое решение с каждым вызовом.Скажем, у вас есть 3 решения, S0, S1, S2
.Решатель может дать вам S1
, затем S2
, затем S1
, затем S1
, затем S0
и т. Д. Если вы знаете, сколько существует решений, вы можете остановиться, как только увидите ихвсе.Как правило, однако, вы не знаете этого заранее.
Однако, что может сделать ГСЧ, это проверить, является ли решение, которое вы предлагаете, правильным.Если вы перебираете все возможные решения, вы можете отфильтровать только те, которые являются правильными.В вашем случае у вас есть 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
.