Randomization error

I’m having the following simple class where in I need the arr elements such that the sum of each row as well as sum of each col is equal to the total elements.
the num of elements determine the shape (rows/cols) of the 2d arr.


class arr_2d_size;
  rand int arr[][], arr_t[][];
  rand int num_elem;
  rand int cols, rows;

  constraint size_c{
    (cols * rows) == num_elem;
    rows == cols; // need this so that the sum constraints work on both rows and cols
    cols > 0;
    rows > 0;
    
    //actual arr
    arr.size == rows;
    foreach(arr[i])
      arr[i].size == cols;
    
    foreach(arr[i,j]){
      arr[i][j] inside {[0:num_elem*num_elem]}; // only positive values
    }
      
    //helper arr
    arr_t.size == cols;
    foreach(arr_t[i])
      arr_t[i].size == rows;
  }
  
  constraint row_sum_c{
    foreach(arr[i])
      arr[i].sum == num_elem;
  }
  
  constraint trans_c{
    foreach(arr_t[i,j])
      arr_t[i][j] == arr[j][i];
  }
  
  
  constraint col_sum_c{
    foreach(arr_t[i])
      arr_t[i].sum == num_elem;
  }
  
endclass

module arr_elem;
  initial begin
    arr_2d_size a = new();
    for(int i = 0 ; i < 10; i ++) begin
      if(! a.randomize() with {num_elem == 4;}) // gives constraint solver error - why? if rows==cols is not provided
        $error("failed with num_elem == 4 ");
      //a.randomize() with {rows == 3; cols == 3;}; // this works
    end
    
  end
  
endmodule

for num_elem == 4, the possible solutions are one of the following …
‘{’{4, 0} , '{0, 4} }
‘{’{1, 3} , '{3, 1} }
‘{’{0, 4} , '{4, 0} }
‘{’{2, 2} , '{2, 2} }
‘{’{3, 1} , '{1, 3} }

My question is … when I provide the constraint rows==cols, it always picks up one of the above solutions. but when this constraint is not used, and num_elem == 4, we can have the following combinations for rows and cols
rows = 1, cols = 4 (a)
rows = 2, cols = 2 (b)
rows = 4, cols = 1 (c)

and when the solver picks a/c, it will fail.
When I run this for say 10 times, without the above constraint (rows == cols), I see it fails about 60% of the time irrespective of the simulator I use (from edaplayground)

since option (b) is possible, should the constraint solver not provide a solution based on this always? why does it fail? Is there any requirement on the constraint solver to provide a case when it is available rather than fail?

In reply to kalai12345:

This is explained at the end of section 18.5.8.1 foreach iterative constraints and applies to the sum(0 constraint as well. All constraints involving the size of a dynamic array are picked before solving the constraints on the individual elements. Then the size of the array becomes a state variable. It is not required to backtrack and pick a new size for the array if the elements constraints cannot be satisfied.