Split an array equally and unique

How do I write a constraint to split an array equally and uniquely.

For ex if:
array = {1,2,3,4,5,6,2,4}; // Here 2 numbers are repeated (2,4).

Then,
array_1 = {2,3,4,5};
array_2 = {1,2,4,6};

Another example:
if
array = {1,2,3,4,5,6,2,4,5,7}; // Here 3 numbers are repeated (2,4,5)

Then,
array_1 = {2,3,4,5,7};
array_2 = {1,2,4,6,5};

Please let me know.

Assumptions:
Array is always even
An element cannot be repeated more than twice in array

What have you tried so far? What is working? What is not working?

What if your array has an odd number of elements? What if a number is repeated more than twice?

You need to provide more details on what behavior you expect.

Hi Shivam,

Assumed array size is even.

And below logic worked for me.

class simple;

rand int arr[];
rand int arr1[];
rand int arr2[];

constraint c_values{
 
  arr.size() inside {[8:20]};
  arr1.size() == arr.size()/2;
  arr2.size() == arr.size()/2;
  arr.size() == arr1.size()+arr2.size();
 
  foreach(arr[i]){  //This will generate max of 2 values are repeated.
    arr[i] inside {[5:30]};
    arr.sum() with(int'(item==arr[i]))<3;
    
  }
  foreach(arr[i]){
    if(i<arr.size()/2){
        arr1[i] == arr[i]; 
    }
  }
  
  foreach(arr[i]){
    if(i<arr.size()/2){
       arr2[i] == arr[arr1.size()+i];  
    }
  }
}

function void post_randomize();
//  arr.sort();

$display("The array size values are arr1= %0d arr2= %0d arr= %0d", arr1.size(), arr2.size(), arr.size());
  $display("Array values = %0p", arr); 
      $display("Arr1 values = %0p", arr1);     
      $display("Arr1 values = %0p", arr2);

endfunction

endclass

Result::

The array size values are arr1= 9 arr2= 9 arr= 18
Array values = '{14, 25, 13, 21, 27, 13, 29, 29, 20, 10, 28, 8, 21, 6, 11, 9, 30, 27}
Arr1 values = '{14, 25, 13, 21, 27, 13, 29, 29, 20}
Arr1 values = '{10, 28, 8, 21, 6, 11, 9, 30, 27}

I tried by constraining array_1 and array_2 unique and for them to be inside array. However unique is not working as expected, since it’s not dividing the numbers equally from array.

Assumptions:
Array is always even
An element cannot be repeated more than twice in array

Hi, your solution doesn’t split array uniquely. For ex, in your output, arr1 has 13 repeated twice.

// Code your testbench here
// or browse Examples
module check;
  
  class random;
    rand bit[5:0] a[],a1[],a2[];
    
    constraint array_sizes {(a.size) inside {[15:25]}; a.size %2 == 0; }
    constraint arr { a1.size == (a.size/2); a2.size == a.size/2 ;}
    //constraint unique_arr {unique{a};} 
    constraint unique_arr {foreach(a[i]) {
      						foreach(a[j]) {
                              if(j != i) { a[j] inside {[1:50]}; a[j] != a[i]; } 
      }}} 
    constraint split {foreach(a[i]) {
        if(i <= ((a.size/2)-1)) a1[i] == a[i]; else a2[i-(a.size/2)] == a[i];}}
    
  endclass
  
  initial begin
    random r;
    r = new;
    assert(r.randomize());
    $display("%p \n %p \n %p",r.a,r.a1,r.a2);
  end
  
endmodule

output : 
'{'h1b, 'h24, 'h32, 'h7, 'h2c, 'h1e, 'h10, 'h15, 'h30, 'h1f, 'h4, 'h5, 'ha, 'h19, 'h16, 'h1, 'h29, 'h6, 'h11, 'h14, 'h28, 'h2f, 'h13, 'h1a} 
 '{'h1b, 'h24, 'h32, 'h7, 'h2c, 'h1e, 'h10, 'h15, 'h30, 'h1f, 'h4, 'h5} 
 '{'ha, 'h19, 'h16, 'h1, 'h29, 'h6, 'h11, 'h14, 'h28, 'h2f, 'h13, 'h1a}
module top;
  class A;
     int array[] = {1,2,3,4,5,6,2,4,5,7}; // Here 3 numbers are repeated (2,4,5)
     rand int arr1[], arr2[];
     constraint c {
		   arr1.size() == array.size/2;
		   arr2.size() == array.size/2;
		   foreach(array[i]) 
		   if (array.sum() with (int'(item == array[i])) == 2 ) {
	             // element is repeated must be in both arr1 and arr2
	             array[i] inside {arr1} && array[i] inside {arr2};
                     } else {
	             // element is not repeated must be in arr1 exclusive arr2
	             (array[i] inside {arr1}) != (array[i] inside {arr2});
                     }
		   }
       endclass
   
   A h = new;
   initial repeat(2) begin
      assert(h.randomize());
      $display("arr1: %p arr2: %p",h.arr1, h.arr2);
   end
endmodule
2 Likes
class pattern;
  rand bit [7:0] a[];
  rand bit [7:0] a1[], a2[];
  
  // An element cannot be repeated more than twice in array
  constraint C1{
    a.size() == 10;
    foreach(a[i]) a[i] inside {[1:9]};
    foreach(a[i]) {
      a.sum() with (int'(item == a[i])) inside {[1:2]};
    }        
  }
  
  // split an array equally and uniquely.
  constraint C2{
    a1.size() == a.size()/2;
    a2.size() == a.size()/2;
    
    unique{a1};
    unique{a2};
    
    foreach(a1[i]) { 
      (a1[i] == a[i*2]) && (a2[i] == a[i*2+1]);      
    }        
  }
endclass

module top();
  pattern p = new();
  
  initial begin
    repeat(10) begin
      assert(p.randomize);
      //p.a.sort(); p.a1.sort(); p.a2.sort();
      $display("%p => %p, %p",p.a,p.a1,p.a2);
    end
  end
endmodule

Output:
'{'h4, 'h6, 'h3, 'h2, 'h1, 'h8, 'h9, 'h9, 'h2, 'h4} => '{'h4, 'h3, 'h1, 'h9, 'h2} , '{'h6, 'h2, 'h8, 'h9, 'h4}
'{'h8, 'h2, 'h9, 'h4, 'h7, 'h6, 'h6, 'h3, 'h2, 'h1} => '{'h8, 'h9, 'h7, 'h6, 'h2} , '{'h2, 'h4, 'h6, 'h3, 'h1}
'{'h7, 'h7, 'h5, 'h1, 'h9, 'h6, 'h4, 'h8, 'h6, 'h9} => '{'h7, 'h5, 'h9, 'h4, 'h6} , '{'h7, 'h1, 'h6, 'h8, 'h9}
'{'h6, 'h2, 'h2, 'h3, 'h3, 'h5, 'h7, 'h9, 'h8, 'h6} => '{'h6, 'h2, 'h3, 'h7, 'h8} , '{'h2, 'h3, 'h5, 'h9, 'h6}
'{'h5, 'h4, 'h1, 'h7, 'h2, 'h8, 'h9, 'h9, 'h3, 'h5} => '{'h5, 'h1, 'h2, 'h9, 'h3} , '{'h4, 'h7, 'h8, 'h9, 'h5}
'{'h3, 'h1, 'h8, 'h7, 'h2, 'h5, 'h9, 'h8, 'h5, 'h2} => '{'h3, 'h8, 'h2, 'h9, 'h5} , '{'h1, 'h7, 'h5, 'h8, 'h2}
'{'h8, 'h6, 'h6, 'h2, 'h1, 'h3, 'h4, 'h8, 'h9, 'h7} => '{'h8, 'h6, 'h1, 'h4, 'h9} , '{'h6, 'h2, 'h3, 'h8, 'h7}
'{'h9, 'h4, 'h4, 'h5, 'h8, 'h7, 'h6, 'h6, 'h7, 'h2} => '{'h9, 'h4, 'h8, 'h6, 'h7} , '{'h4, 'h5, 'h7, 'h6, 'h2}
'{'h8, 'h4, 'h5, 'h7, 'h3, 'h5, 'h7, 'h9, 'h2, 'h3} => '{'h8, 'h5, 'h3, 'h7, 'h2} , '{'h4, 'h7, 'h5, 'h9, 'h3}
'{'h7, 'h3, 'h2, 'h5, 'h1, 'h6, 'h9, 'h2, 'h3, 'h9} => '{'h7, 'h2, 'h1, 'h9, 'h3} , '{'h3, 'h5, 'h6, 'h2, 'h9}

Run on EdaPlayground

Thanks Dave for the interesting solution. It worked.

I was looking to understand in detail how array.sum works with item. Do you have any pointers that you can provide?

Thanks for the reply. I missed to mention that array cannot be unique. So your code won’t work.