Conflicting soft constraint behavior

I have a test file where the behavior seems to be wrong. I see that in all generations, num_of_red_shoes is high, while I expect a more even distribution. What is the reason for this behavior and how can it be corrected?

<'
struct closet {
    kind:[SMALL,BIG];

    num_of_shoes:uint;
    num_of_red_shoes:uint;
    num_of_black_shoes:uint;
    num_of_yellow_shoes:uint;

    keep soft num_of_red_shoes < 10;
    keep soft num_of_black_shoes < 10;
    keep soft num_of_yellow_shoes < 10;

    keep num_of_yellow_shoes + num_of_black_shoes + num_of_red_shoes == num_of_shoes;

    when BIG closet {
        keep num_of_shoes in [50..100];
    };
};

extend sys {
    closets[100]:list of BIG closet;
};
'>

      

Generation results:

item   type        kind        num_of_sh*  num_of_re*  num_of_bl*  num_of_ye* 
---------------------------------------------------------------------------
0.     BIG closet  BIG         78          73          1           4           
1.     BIG closet  BIG         67          50          8           9           
2.     BIG closet  BIG         73          68          0           5           
3.     BIG closet  BIG         73          66          3           4           
4.     BIG closet  BIG         51          50          0           1           
5.     BIG closet  BIG         78          76          1           1           
6.     BIG closet  BIG         55          43          7           5           
7.     BIG closet  BIG         88          87          1           0           
8.     BIG closet  BIG         99          84          6           9           
9.     BIG closet  BIG         92          92          0           0           
10.    BIG closet  BIG         63          55          3           5           
11.    BIG closet  BIG         59          50          9           0           
12.    BIG closet  BIG         51          44          2           5           
13.    BIG closet  BIG         82          76          1           5           
14.    BIG closet  BIG         81          74          2           5           
15.    BIG closet  BIG         97          93          2           2           
16.    BIG closet  BIG         54          41          8           5           
17.    BIG closet  BIG         55          44          5           6           
18.    BIG closet  BIG         70          55          9           6           
19.    BIG closet  BIG         63          57          1           5  

      

+3


source to share


4 answers


When conflicting soft constraints exist, Specman does not randomize the soft programs that apply, but rather prioritizes the constraints that were most recently written. Since the soft red shoe was the first in the test, it was always redefined.

If the software is known to be mutually exclusive (which is not the case here), you can use a simple flag to randomly choose which software to hold. for example the code will look like this:

flag:uint[0..2];

keep soft read_only(flag==0) => num_of_red_shoes < 10;
keep soft read_only(flag==1) => num_of_black_shoes < 10;
keep soft read_only(flag==2) => num_of_yellow_shoes < 10;

      



However, since it is not known beforehand how many soft will be held (and it is possible, and two or all three will be satisfied), a more complex decision must be made. Here's the code that does this randomization:

struct closet {
    kind:[SMALL,BIG];

    num_of_shoes:uint;
    num_of_red_shoes:uint;
    num_of_black_shoes:uint;
    num_of_yellow_shoes:uint;

    //replaces the original soft constraints (if a flag is true the correlating
    //right-side implication will be enforced
    soft_flags[3]:list of bool;
    keep for each in soft_flags {
        soft it == TRUE;
    };

    //this list is used to shuffle the flags so their enforcement will be done
    //with even distribution
    soft_indices:list of uint;
    keep soft_indices.is_a_permutation({0;1;2});

    keep soft_flags[soft_indices[0]] => num_of_red_shoes < 10;
    keep soft_flags[soft_indices[1]] => num_of_black_shoes < 10;
    keep soft_flags[soft_indices[2]] => num_of_yellow_shoes < 10;

    keep num_of_yellow_shoes + num_of_black_shoes + num_of_red_shoes == num_of_shoes;
};

      

+3


source


I am not with Cadence, so I cannot give you a definite answer. I think the solver will try to break as few constraints as possible and it just picks the first one if it finds one (in your case, the one that fits red shoes). Try changing the order and see if that changes (if the black constraint comes first, I think you'll always get more black boots).

As a solution, you can simply remove soft constraints when you have a large closet:

when BIG closet {
    keep num_of_red_shoes.reset_soft();
    keep num_of_black_shoes.reset_soft();
    keep num_of_yellow_shoes.reset_soft();
    keep num_of_shoes in [50..100];
};

      



If you want to randomly choose which one to disable (sometimes more than 10 red boots, sometimes more than 10 black boots, etc.), then you need an auxiliary field:

when BIG closet {
    more_shoes : [ RED, BLACK, YELLOW ];

    keep more_shoes == RED => num_of_red_shoes.reset_soft();
    keep more_shoes == BLACK => num_of_black_shoes.reset_soft();
    keep more_shoes == YELLOW => num_of_yellow_shoes.reset_soft();
    keep num_of_shoes in [50..100];
};

      

It depends on what you mean by "more even distribution".

+1


source


It is impossible to satisfy all your hard and soft limits for a BIG cabinet. So Speckman tries to find a solution by ignoring some of your soft constraints. IntelliGen's constraint solver does not ignore all soft constraints, but tries to find a solution while still using a subset. This is explained in the "Specman Generator User Guide" (sn_igenuser.pdf):

[S] oft restrictions that are loaded later are considered higher priority than previously loaded soft restrictions.

In this case, it means that Specman is dropping the soft constraint on red shoes, and since it can find a solution that still obeys other soft constraints, it does not drop them.

If you combine all your soft constraints into one, then you are likely to get the result you were hoping for:

 keep soft ((num_of_red_shoes    < 10) and (num_of_black_shoes < 10) and
            (num_of_yellow_shoes < 10));

      

There are advantages to prioritizing later constraints: this means that with AOP you can add new soft constraints and they will be given the highest priority.

+1


source


For more distributed values, I would suggest the following. I'm sure you can follow the intended logic too.

var1, var2 : uint;
keep var1 in [0..30];
keep var2 in [0..30];

when BIG closet {
    keep num_of_shoes in [50..100];
    keep num_of_yellow_shoes == (num_of_shoes/3) - 15 + var1;
    keep num_of_black_shoes == (num_of_shoes - num_of_yellow_shoes)/2 - 15 + var2;
    keep num_of_red_shoes == num_of_shoes - (num_of_yellow_shoes - num_of_black_shoes);

keep gen (var1, var2) before (num_of_shoes);
    keep gen (num_of_shoes) before (num_of_yellow_shoes, num_of_black_shoes, num_of_red_shoes);
    keep gen (num_of_yellow_shoes) before (num_of_black_shoes, num_of_red_shoes);
    keep gen (num_of_black_shoes) before (num_of_red_shoes);
};

      

+1


source







All Articles