Promela同时随机select两个元素
Promela randomly select two elements at the same time
最近我开始学习 Promela,我想建模从有 10 个黑球和 4 个白球的盒子中挑选两个球,我可以将盒子建模为数组,但我不知道如何 select同时2个球。从剩下的那些中挑选一个然后另一个改变概率。你有什么想法吗?
当你需要从[=16=的连续区间[LOW, UPP]
中提取仅一对值idx
和idy
时] 数字,您可以通过以下方式轻松解决保证 idx != idy
的问题:
- 在
[LOW, UPP]
中选择idx
- 在
[LOW, UPP - 1]
中挑选idy
调整 idy
wrt 的值。 idx
的值如下:
idy = LOW + (((idx - LOW) + 1 + (idy - LOW)) % N)
也就是说,您将 idy
解释为固定位移 wrt。 idx
。请注意,这种方法不会影响 idy
的概率分布,特别是,从概率的角度来看,它不会使 idy
依赖于 idx
。
示例:
#define BLACK_BALLS 4
#define WHITE_BALLS 10
#define TOTAL_BALLS 14
bool box[TOTAL_BALLS];
inline my_select(var, upper) {
if
:: 0 <= upper -> var = 0;
:: 1 <= upper -> var = 1;
:: 2 <= upper -> var = 2;
:: 3 <= upper -> var = 3;
:: 4 <= upper -> var = 4;
:: 5 <= upper -> var = 5;
:: 6 <= upper -> var = 6;
:: 7 <= upper -> var = 7;
:: 8 <= upper -> var = 8;
:: 9 <= upper -> var = 9;
:: 10 <= upper -> var = 10;
:: 11 <= upper -> var = 11;
:: 12 <= upper -> var = 12;
:: 13 <= upper -> var = 13;
fi;
}
proctype pick_two_balls() {
byte idx;
byte idy;
my_select(idx, TOTAL_BALLS - 1);
my_select(idy, TOTAL_BALLS - 2);
printf("Initial picks:\n")
printf("\tpicked %d in [0, %d]\n", idx, TOTAL_BALLS - 1);
printf("\tpicked %d in [0, %d]\n", idy, TOTAL_BALLS - 2);
idy = ((idx + 1) + idy) % (TOTAL_BALLS);
printf("Adjusted picks:\n");
printf("\tball #01 at index %d\n", idx);
printf("\tball #02 at index %d\n", idy);
printf("Final Balls:\n");
if
:: box[idx] -> printf("\tbox[%d] = black\n", idx);
:: !box[idx] -> printf("\tbox[%d] = white\n", idx);
fi;
if
:: box[idy] -> printf("\tbox[%d] = black\n", idy);
:: !box[idy] -> printf("\tbox[%d] = white\n", idy);
fi;
}
init {
byte idx = 0;
byte todo = BLACK_BALLS;
do // not guaranteed to terminate!
:: todo > 0 ->
my_select(idx, TOTAL_BALLS - 1) ->
if
:: box[idx] ->
skip;
:: else ->
box[idx] = true;
todo = todo - 1;
fi;
:: else ->
break;
od;
for (idx: 0 .. TOTAL_BALLS - 1) {
if
:: box[idx] ->
printf("box[%d] = black\n", idx);
:: !box[idx] ->
printf("box[%d] = white\n", idx);
fi;
}
run pick_two_balls();
}
输出:
~$ spin p.pml
box[0] = white
box[1] = black
box[2] = white
box[3] = white
box[4] = white
box[5] = white
box[6] = white
box[7] = white
box[8] = white
box[9] = white
box[10] = white
box[11] = black
box[12] = black
box[13] = black
Initial picks:
picked 9 in [0, 13]
picked 7 in [0, 12]
Adjusted picks:
ball #01 at index 9
ball #02 at index 3
Final Balls:
box[9] = white
box[3] = white
2 processes created
注意#1: 在正常情况下,我会使用 select
statement instead of writing my own my_select(var, upper)
function. However, select
并不能保证分配给 var
的值是用均匀分布,我认为这对您来说可能是个问题。
注意#2:当您需要提取多于一对索引时,上面的数学表达式没有帮助。但是,您可以在机械意义上应用相同的原则:将 used_indexes
维护为 bool 的支持数组,其中如果某些索引使用位置 k
则为 true
。每次选择一个新索引 i
时,您都会从数组的开头开始计算空单元格,并将 i
减一。一旦 i = 0
你有了应该在原始数组中使用的 "real index" j
,所以你将该位置标记为在 used_indexes
.
最近我开始学习 Promela,我想建模从有 10 个黑球和 4 个白球的盒子中挑选两个球,我可以将盒子建模为数组,但我不知道如何 select同时2个球。从剩下的那些中挑选一个然后另一个改变概率。你有什么想法吗?
当你需要从[=16=的连续区间[LOW, UPP]
中提取仅一对值idx
和idy
时] 数字,您可以通过以下方式轻松解决保证 idx != idy
的问题:
- 在
[LOW, UPP]
中选择 - 在
[LOW, UPP - 1]
中挑选 调整
idy
wrt 的值。idx
的值如下:idy = LOW + (((idx - LOW) + 1 + (idy - LOW)) % N)
idx
idy
也就是说,您将 idy
解释为固定位移 wrt。 idx
。请注意,这种方法不会影响 idy
的概率分布,特别是,从概率的角度来看,它不会使 idy
依赖于 idx
。
示例:
#define BLACK_BALLS 4
#define WHITE_BALLS 10
#define TOTAL_BALLS 14
bool box[TOTAL_BALLS];
inline my_select(var, upper) {
if
:: 0 <= upper -> var = 0;
:: 1 <= upper -> var = 1;
:: 2 <= upper -> var = 2;
:: 3 <= upper -> var = 3;
:: 4 <= upper -> var = 4;
:: 5 <= upper -> var = 5;
:: 6 <= upper -> var = 6;
:: 7 <= upper -> var = 7;
:: 8 <= upper -> var = 8;
:: 9 <= upper -> var = 9;
:: 10 <= upper -> var = 10;
:: 11 <= upper -> var = 11;
:: 12 <= upper -> var = 12;
:: 13 <= upper -> var = 13;
fi;
}
proctype pick_two_balls() {
byte idx;
byte idy;
my_select(idx, TOTAL_BALLS - 1);
my_select(idy, TOTAL_BALLS - 2);
printf("Initial picks:\n")
printf("\tpicked %d in [0, %d]\n", idx, TOTAL_BALLS - 1);
printf("\tpicked %d in [0, %d]\n", idy, TOTAL_BALLS - 2);
idy = ((idx + 1) + idy) % (TOTAL_BALLS);
printf("Adjusted picks:\n");
printf("\tball #01 at index %d\n", idx);
printf("\tball #02 at index %d\n", idy);
printf("Final Balls:\n");
if
:: box[idx] -> printf("\tbox[%d] = black\n", idx);
:: !box[idx] -> printf("\tbox[%d] = white\n", idx);
fi;
if
:: box[idy] -> printf("\tbox[%d] = black\n", idy);
:: !box[idy] -> printf("\tbox[%d] = white\n", idy);
fi;
}
init {
byte idx = 0;
byte todo = BLACK_BALLS;
do // not guaranteed to terminate!
:: todo > 0 ->
my_select(idx, TOTAL_BALLS - 1) ->
if
:: box[idx] ->
skip;
:: else ->
box[idx] = true;
todo = todo - 1;
fi;
:: else ->
break;
od;
for (idx: 0 .. TOTAL_BALLS - 1) {
if
:: box[idx] ->
printf("box[%d] = black\n", idx);
:: !box[idx] ->
printf("box[%d] = white\n", idx);
fi;
}
run pick_two_balls();
}
输出:
~$ spin p.pml
box[0] = white
box[1] = black
box[2] = white
box[3] = white
box[4] = white
box[5] = white
box[6] = white
box[7] = white
box[8] = white
box[9] = white
box[10] = white
box[11] = black
box[12] = black
box[13] = black
Initial picks:
picked 9 in [0, 13]
picked 7 in [0, 12]
Adjusted picks:
ball #01 at index 9
ball #02 at index 3
Final Balls:
box[9] = white
box[3] = white
2 processes created
注意#1: 在正常情况下,我会使用 select
statement instead of writing my own my_select(var, upper)
function. However, select
并不能保证分配给 var
的值是用均匀分布,我认为这对您来说可能是个问题。
注意#2:当您需要提取多于一对索引时,上面的数学表达式没有帮助。但是,您可以在机械意义上应用相同的原则:将 used_indexes
维护为 bool 的支持数组,其中如果某些索引使用位置 k
则为 true
。每次选择一个新索引 i
时,您都会从数组的开头开始计算空单元格,并将 i
减一。一旦 i = 0
你有了应该在原始数组中使用的 "real index" j
,所以你将该位置标记为在 used_indexes
.