question

Peter W8 avatar image
0 Likes"
Peter W8 asked Felix Möhlmann commented

How to label items according to percentage and restrictions?

I need to create labels according to the following percentage:

Label AMT_G: 50%

Label AMT_RET: 21%

Label AMT_EXT_ULC: 7%

Label AMT_PIGG: 2%

Label AMT_PS: 2%

Label AMT_HYB: 1%

Label AMT_DUAL: 8%

Label PIE: 2%

Label PIE_RET: 7%


For this I use a trigger "Set Label by Percentage" at the source.

However, certain labels are not allowed to be created one after another. This applies to all labels except AMT_G and AMT_DUAL which are allowed to be created one after another. The creation restriction for the other labels should be as following:

AMT_RET: Max 1/4

AMT_EXT_ULC: Max 1/7

AMT_PIGG: Max 1/18

AMT_PS: Max 1/4

AMT_HYB: Max 1/4

PIE: Max 1/8

PIE_RET: Max 1/8

So for instance 7% of all created labels should be "PIE_RET" but "PIE_RET" is not to be created more often than every eight label. How do I achieve this?

I've uploaded my model ("LabelingWithPercentandFreq") to the flexsim file share site.


FlexSim 22.1.1
labelsby percentagerestrictioncreation
5 |100000

Up to 12 attachments (including images) can be used with a maximum of 23.8 MiB each and 47.7 MiB total.

Felix Möhlmann avatar image
0 Likes"
Felix Möhlmann answered Felix Möhlmann commented

My approach would be to build upon the "Set Label By Percentage" option. With labels the object can keep track of whether a label value is allowed to be assigned or not (as a combination of the min. intervals and the number of items since that label was last assigned). If the value can not be assigned right now, it is written to an array of pending values and a new random value is generated until the label can be assigned. This is done to not alter the quantity of how often a value is assigned overall, but only delay assigning it. Each time the trigger fires, the code first checks if any of the pending values can now be assigned. If not, or there aren't any, it goes back to generating random values.

In the example model that is linked below I use a bundle label on the source to keep track of when the values can be assigned. The "AllowedIn" column is set to the "MinInterval" value when the value is used and decremented each time a new item is generated. If the number in that column is 0, the value is allowed to be assigned.

1661339087426.png

The "Value" column is indexed (Rightclick on the column header to see the option), for fast lookup of the correct row in the code.

As mentioned above, the default "Set Label By Percentage" option forms the basis of the code with the rest added around it.

  1. int stream = getstream(current);
  2. // Decrement bundle "AllowedIn" column
  3. treenode bundleLabel = current.labels["MinIntervals"];
  4. int numRows = getbundlenrentries(bundleLabel);
  5. for(int i = 0; i < numRows; i++)
  6. {
  7.     setbundlevalue(bundleLabel, i, "AllowedIn", Math.max(0, getbundlevalue(bundleLabel, i, "AllowedIn")-1));
  8. }
  9.  
  10. // Get next number
  11. // Check value queue first
  12. for(int j = 1; j <= current.ValueQueue.length; j++)
  13. {
  14.     Variant value = current.ValueQueue[j];
  15.     // Check if number is allowed
  16.     int bundleRow = getbundleindexentries(bundleLabel, "Value", value)[1];
  17.     if(getbundlevalue(bundleLabel, bundleRow, "AllowedIn") == 0)
  18.     {
  19.         // If so, set "AllowedIn" column, assign label, remove from array and terminate
  20.         setbundlevalue(bundleLabel, bundleRow, "AllowedIn", getbundlevalue(bundleLabel, bundleRow, "MinInterval"));
  21.         item.labels.assert("Type").value = value;
  22.         current.ValueQueue.shift();
  23.         return 0;
  24.     }
  25. }
  26. while(true)
  27. {
  28.     double randomnum = uniform(0.0, 100.0, stream);
  29.     string labelname = "Type";
  30.     Object involved = item;
  31.     Variant value;
  32.     double total = 0.0;
  33.     int foundmatch = 0;
  34.  
  35.     total += 50;
  36.     if (!foundmatch && randomnum <= total) {
  37.         value = "AMT_G";
  38.         foundmatch = 1;
  39.     }
  40.     total += 21;
  41.     if (!foundmatch && randomnum <= total) {
  42.         value = "AMT_RET";
  43.         foundmatch = 1;
  44.     }
  45.     total += 7;
  46.     if (!foundmatch && randomnum <= total) {
  47.         value = "AMT_EXT_ULC";
  48.         foundmatch = 1;
  49.     }
  50.     total += 2;
  51.     if (!foundmatch && randomnum <= total) {
  52.         value = "AMT_PIGG";
  53.         foundmatch = 1;
  54.     }
  55.     total += 2;
  56.     if (!foundmatch && randomnum <= total) {
  57.         value = "AMT_PS";
  58.         foundmatch = 1;
  59.     }
  60.     total += 1;
  61.     if (!foundmatch && randomnum <= total) {
  62.         value = "AMT_HYB";
  63.         foundmatch = 1;
  64.     }
  65.     total += 8;
  66.     if (!foundmatch && randomnum <= total) {
  67.         value = "AMT_DUAL";
  68.         foundmatch = 1;
  69.     }
  70.     total += 2;
  71.     if (!foundmatch && randomnum <= total) {
  72.         value = "PIE";
  73.         foundmatch = 1;
  74.     }
  75.     total += 7;
  76.     if (!foundmatch && randomnum <= total) {
  77.         value = "PIE_RET";
  78.         foundmatch = 1;
  79.     }
  80.  
  81.     // Check if number is allowed
  82.     int bundleRow = getbundleindexentries(bundleLabel, "Value", value)[1];
  83.     if(getbundlevalue(bundleLabel, bundleRow, "AllowedIn") == 0)
  84.     {
  85.         // If so, set "AllowedIn" column, assign label and terminate
  86.         setbundlevalue(bundleLabel, bundleRow, "AllowedIn", getbundlevalue(bundleLabel, bundleRow, "MinInterval"));
  87.         involved.labels.assert(labelname).value = value;
  88.         return 0;
  89.     }
  90.     else
  91.     {
  92.         // If not push to ValueQueue
  93.         current.ValueQueue.push(value);
  94.     }
  95. }

Download model (google drive)


1661339087426.png (7.1 KiB)
· 3
5 |100000

Up to 12 attachments (including images) can be used with a maximum of 23.8 MiB each and 47.7 MiB total.

Peter W8 avatar image
0 Likes"
Peter W8 answered Felix Möhlmann commented

Hi again,

I noticed an issue with one variant, "AMT_RET". That variant does not follow the creation restricton you helped me with. I believe it has to do with that you used a lower case "t" in the name. It should be a capital "T". But when I change it to a capital "T", it reverts back to a lower case "t" everytime I press stop or reset. How do I change it and could this be the reason for "AMT_RET" not taking the restriction into acount?

1663075060076.png


1663075060076.png (7.6 KiB)
· 1
5 |100000

Up to 12 attachments (including images) can be used with a maximum of 23.8 MiB each and 47.7 MiB total.