1 进程的基本表示

进程的普适表示是(x:A→P(x))(x:A \to P(x))(x:AP(x)),意为选择字母表AAA中一动作xxx,在PPP执行过xxx这一动作后接下来的行为记作P(x)P(x)P(x)

A=αPA=\alpha PA=αP表示进程PPP的动作集合。

STOPASTOP_ASTOPA表示无法执行任何动作的进程(注意AAA不同STOPASTOP_ASTOPA不同,但仅在理论意义上区分)。

RUNARUN_ARUNA表示可以执行AAA中任何动作(且仅可以执行这些动作)的进程(注意AAA不同RUNARUN_ARUNA不同),RUNA=(x:A→RUNA)RUN_A = (x:A \to RUN_A)RUNA=(x:ARUNA)

1.1 递归(recursion)

如时钟进程可以无限展开:
CLOCK=(tick→CLOCK)=(tick→(tick→CLOCK))=(tick→(tick→(tick→...CLOCK...))) CLOCK \\ = (tick \to CLOCK) \\ = (tick \to (tick \to CLOCK)) \\ = (tick \to (tick \to (tick \to ... CLOCK ... ))) CLOCK=(tickCLOCK)=(tick(tickCLOCK))=(tick(tick(tick...CLOCK...)))
在CSP里动作(或称事件)是右结合的,所以上式可去除内部括号:
CLOCK=(tick→tick→tick→...CLOCK)CLOCK = (tick \to tick \to tick \to ... CLOCK)CLOCK=(tickticktick...CLOCK)
F(X)=(tick→X)F(X)=(tick \to X)F(X)=(tickX),那么时钟进程实际就是X=F(X)X=F(X)X=F(X)。对于这类形式的进程,F(X)F(X)F(X)XXX前有动作(这里是tickticktick),那么就称这个F(X)F(X)F(X)guardedguardedguarded的,相应的X=F(X)X=F(X)X=F(X)有唯一解(可理解成不存在满足FFF的进程XXX的不等价表示)。此类递归进程可以记为:
μX:A⋅F(X)\mu X:A \cdot F(X)μX:AF(X)
其中AAA是进程XXX的动作集合,即A=αXA=\alpha XA=αX


例如,时钟进程CLOCKCLOCKCLOCK可记为:
CLOCK=μX:{tick}⋅(tick→X)CLOCK=\mu X : \{tick\} \cdot (tick \to X)CLOCK=μX:{tick}(tickX)
又如,简单贩卖机进程VMS=(coin→(choc→VMS))VMS=(coin \to (choc \to VMS))VMS=(coin(chocVMS))可记为:
VMS=μX:{coin,choc}⋅(coin→(choc→X))VMS=\mu X : \{coin,choc\} \cdot(coin \to (choc \to X))VMS=μX:{coin,choc}(coin(chocX))

1.2 选择(choice)

CSP中引入选择是为使进程能够和环境交互,如顾客可在投入硬币(coincoincoin)后选择巧克力(chocchocchoc)或选择太妃糖(toffeetoffeetoffee),这同样是个递归的例子:
VMCT=μX⋅coin→(choc→X ∣ toffee→X)VMCT=\mu X \cdot coin \to (choc \to X \ | \ toffee \to X)VMCT=μXcoin(chocX  toffeeX)
注意,选择是针对不同的动作的,不仅要动作不同才有选择,还要确保在书写时选择符的左右都有直接动作,如(x→P ∣ y→Q ∣ z→R)(x \to P \ | \ y \to Q \ | \ z \to R)(xP  yQ  zR)是合法的,而(x→P ∣ (y→Q ∣ z→R))(x \to P \ | \ (y \to Q \ | \ z \to R))(xP  (yQ  zR))是不合法的,因为选择符右侧没有指明执行哪个动作时进入此分支。

1.3 互递归(mutual recursion)

递归将一个进程定义为一个方程的解,互递归则是使用了多个类似的方程组定义更复杂的执行情况。互递归要保证右侧都是guardedguardedguarded的,每个互递归的小过程在左侧只能出现一次。


例如,可以选择选择饮料(setorangesetorangesetorange,setlemonsetlemonsetlemon)和实际获取饮料(orangeorangeorange,lemonlemonlemon)的饮料机DDDDDD,引入两个辅助过程OOOLLL,表示当前选择的饮料状态,那么:
αDD=αO=αL={setorange,setlemon,orange,lemon}DD=(setorange→O ∣ setlemon→L)O=(orange→O ∣ setlemon→L ∣ setorange→O)L=(lemon→L ∣ setlemon→L ∣ setorange→O) \begin{aligned} \alpha DD & = \alpha O = \alpha L = \{setorange,setlemon,orange,lemon\} \\ DD & = (setorange \to O \ | \ setlemon \to L) \\ O & = (orange \to O \ | \ setlemon \to L \ | \ setorange \to O) \\ L & = (lemon \to L \ | \ setlemon \to L \ | \ setorange \to O) \end{aligned} αDDDDOL=αO=αL={setorange,setlemon,orange,lemon}=(setorangeO  setlemonL)=(orangeO  setlemonL  setorangeO)=(lemonL  setlemonL  setorangeO)

互递归还适合建模一些整数相关的进程,例如一个在地面(0层:CT0CT_0CT0)可以四处移动或向上移动,在空中(n+1层:CTn+1CT_{n+1}CTn+1)可以上下移动的物体:
CT0=(up→CT1 ∣ around→CT0)CTn+1=(up→CTn+2 ∣ down→CTn) \begin{aligned} CT_0 & = (up \to CT_1 \ | \ around \to CT_0) \\ CT_{n+1} & = (up \to CT_{n+2} \ | \ down \to CT_n) \end{aligned} CT0CTn+1=(upCT1  aroundCT0)=(upCTn+2  downCTn)
一个细节值得注意,这里用n+1n+1n+1层而不是用nnn层,自然地保证了>0>0>0(也就是在空中)这一情形,前提是约定n∈Nn \in \mathbb{N}nN

1.4 一些规则
L1:进程等价的递归定义

两进程等价,当且仅当动作集合AAABBB相同,且在执行每个动作xxx后的后续进程P(x)P(x)P(x)Q(x)Q(x)Q(x)也等价。
(x:A→P(x))=(y:B→Q(y))≡(A=B∧∀x:A⋅P(x)=Q(x))(x:A \to P(x)) = (y:B \to Q(y)) \equiv (A=B \wedge \forall x:A \cdot P(x) = Q(x))(x:AP(x))=(y:BQ(y))(A=Bx:AP(x)=Q(x))


  • L1A:STOP≠(d→P)STOP \neq (d \to P)STOP=(dP)
    这表示任何有初始动作的进程都不是STOPSTOPSTOP,因为左侧STOPSTOPSTOP的动作集合是ϕ\phiϕ,而右侧的动作集合中则至少包含了动作ddd

  • L1B:(c→P)≠(d→Q)  if c≠d(c \to P) \neq (d \to Q) \ \ if \ c \neq d(cP)=(dQ)  if c=d
    这表示初始动作不同的进程一定不同。

  • L1C:(c→P ∣ d→Q)=(d→Q ∣ c→P)(c \to P \ | \ d \to Q) = (d \to Q \ | \ c \to P)(cP  dQ)=(dQ  cP)
    这表示选择符号在逻辑意义上是无序的。

  • L1D:(c→P)=(c→Q)≡P=Q(c \to P) = (c \to Q) \equiv P = Q(cP)=(cQ)P=Q
    这表示相同初始动动作的进程等价与否,仅取决于各自的后续行为。
L2:guarded的递归进程具有唯一解

F(X)F(X)F(X)是一个guarded的关于进程XXX的表达式,那么:
(Y=F(Y))≡(Y=μX⋅F(X))(Y=F(Y)) \equiv (Y= \mu X \cdot F(X))(Y=F(Y))(Y=μXF(X))
注意,这里μX⋅F(X)\mu X \cdot F(X)μXF(X)就是其唯一解,只是没能表示成解析解的形式。


  • L2A:μX⋅F(X)=F(μX⋅F(X))\mu X \cdot F(X) = F(\mu X \cdot F(X))μXF(X)=F(μXF(X))
    这表示递归的FFF可以无限展开,展开后的进程与之前总是等价的。

这很有用,只是它太显然了,总是可以不假思索地按需若干次展开递归结构,如证明下面这个互递归里VM1=VMSVM1=VMSVM1=VMS

VM1=(coin→VM2)VM2=(choc→VM1) VM1 = (coin \to VM2) \\ VM2 = (choc \to VM1) VM1=(coinVM2)VM2=(chocVM1)
只要将VM1VM1VM1中的VM2VM2VM2展开一次,得到:

VM1=(coin→VM2)=(coin→(choc→VM1))VM1 = (coin \to VM2) = (coin \to (choc \to VM1))VM1=(coinVM2)=(coin(chocVM1))

它和VMSVMSVMS有相同的递归式,因为这个相同的递归式是guardedguardedguarded的,所以具有唯一解,所以它们等价。

L3:互递归的等价

有一系列互递归的进程XiX_iXi,其具体表达式是Xi=F(i,X)X_i = F(i,X)Xi=F(i,X),那么:
if  (∀i:S⋅(Xi=F(i,X)∧Yi=F(i,Y)))  then  X=Yif \ \ (\forall i:S \cdot (X_i = F(i,X) \wedge Y_i = F(i,Y))) \ \ then \ \ X=Yif  (i:S(Xi=F(i,X)Yi=F(i,Y)))  then  X=Y
即若互递归进程的对应项是等价进程时,两互递归进程(它们两者之间不是互递归的)是等价的。注意这里用的是if−thenif-thenifthen而不是iffiffiff,也就是说反过来是不成立的,即从互递归等价无法推断出存在等价的互递归项。

2 迹(trace)及其操作

迹表示进程中从一动作执行到一动作位置的动作序列,也可以什么动作都没执行,得到的就是空的迹⟨⟩\langle \rangle

VMSVMSVMS服务了一个顾客,并到下一顾客投币完成为止的迹:
⟨coin,choc,coin⟩\langle coin,choc,coin \ranglecoin,choc,coin

2.1 迹上连接(catenation)

sssttt的连接记作s⌢ts^\smallfrown tst,如⟨coin,choc⟩⌢⟨coin,toffee⟩=⟨coin,choc,coin,toffee⟩\langle coin,choc \rangle^\smallfrown \langle coin,toffee \rangle = \langle coin,choc,coin,toffee \ranglecoin,choccoin,toffee=coin,choc,coin,toffee。连接具备如下性质:
s⌢⟨⟩=⟨⟩⌢s=ss⌢(t⌢u)=(s⌢t)⌢us⌢t=s⌢u≡t=us⌢t=u⌢t≡s=us⌢t=⟨⟩≡s=⟨⟩∧t=⟨⟩ s^\smallfrown \langle \rangle = \langle \rangle ^\smallfrown s = s \\ s^\smallfrown (t^\smallfrown u)=(s^\smallfrown t)^\smallfrown u \\ s^\smallfrown t = s^\smallfrown u \equiv t = u \\ s^\smallfrown t = u^\smallfrown t \equiv s=u \\ s^\smallfrown t = \langle \rangle \equiv s=\langle \rangle \wedge t=\langle \rangle s=s=ss(tu)=(st)ust=sut=ust=uts=ust=s=t=
用右上标自然数表示迹的多次自连接:
t0=⟨⟩tn+1=t⌢tn=tn⌢t(s⌢t)n+1=s⌢(t⌢s)n⌢t t^0=\langle \rangle \\ t^{n+1}=t^\smallfrown t^n=t^{n\smallfrown} t \\ (s^\smallfrown t)^{n+1} = s^\smallfrown (t^\smallfrown s)^{n\smallfrown} t t0=tn+1=ttn=tnt(st)n+1=s(ts)nt

2.2 限定(restriction),或称投影

⟨around,up,down,around⟩↾{up,down}=⟨up,down⟩\langle around,up,down,around \rangle \upharpoonright \{up,down\}=\langle up,down \ranglearound,up,down,around{up,down}=up,down。迹投影到集合上,只保留迹在集合中出现的那些动作。投影具备如下性质:
⟨⟩↾A=⟨⟩(s⌢t)↾A=(s↾A)⌢(t↾A)⟨x⟩↾A=⟨x⟩   if x∈A⟨y⟩↾A=⟨⟩     if y∉As↾{}=⟨⟩(s↾A)↾B=s↾(A∩B) \langle \rangle \upharpoonright A = \langle \rangle \\ (s^\smallfrown t) \upharpoonright A = (s \upharpoonright A)^\smallfrown (t \upharpoonright A) \\ \langle x \rangle \upharpoonright A = \langle x \rangle \ \ \ if \ x\in A \\ \langle y \rangle \upharpoonright A = \langle \rangle \ \ \ \ \ if \ y \notin A \\ s \upharpoonright \{\} = \langle \rangle \\ (s \upharpoonright A) \upharpoonright B = s \upharpoonright (A \cap B) A=(st)A=(sA)(tA)xA=x   if xAyA=     if y/As{}=(sA)B=s(AB)

2.3 头(head)和尾(tail)

这和编译原理或系统分析等课程中的定义是一样的,用下标“0_00”表示头,用上标“′'”表示尾,如:
⟨x,y,x⟩0=x⟨x,y,x⟩′=⟨y,x⟩ \langle x,y,x \rangle_0 = x \\ \langle x,y,x \rangle' = \langle y,x \rangle x,y,x0=xx,y,x=y,x
取头尾操作具备如下性质:
(⟨x⟩⌢s)0=x(⟨x⟩⌢s)′=ss=(⟨s0⟩⌢s′)    if s≠⟨⟩s=t≡(s=t=⟨⟩∨(s0=t0∧s′=t′)) (\langle x \rangle^\smallfrown s)_0 = x \\ (\langle x \rangle^\smallfrown s)' = s \\ s = (\langle s_0 \rangle ^\smallfrown s') \ \ \ \ if \ s \neq \langle \rangle \\ s = t \equiv (s=t=\langle \rangle \vee (s_0=t_0 \wedge s'=t')) (xs)0=x(xs)=ss=(s0s)    if s=s=t(s=t=(s0=t0s=t))

2.4 star操作(带序幂集转迹)

A∗A^*A表示AAA中元素组成的所有迹的集合,也就是AAA的元素可重复的带序幂集,将其中每个序列当作迹看待即可:
A∗={s ∣ s↾A=s}A^* = \{s \ | \ s \upharpoonright A = s \}A={s  sA=s}
这个定义中是从另一个角度诠释,也就是所有投影在AAA上不变的迹的集合。star操作具备如下性质:
⟨⟩∈A∗⟨x⟩∈A∗≡x∈A(s⌢t)∈A∗≡s∈A∗∧t∈A∗A∗={t ∣ t=⟨⟩∨(t0∈A∧t′∈A∗)} \langle \rangle \in A^* \\ \langle x \rangle \in A^* \equiv x \in A \\ (s^\smallfrown t) \in A^* \equiv s \in A^* \wedge t \in A^* \\ A^* = \{ t \ | \ t=\langle \rangle \vee (t_0 \in A \wedge t' \in A^*)\} AxAxA(st)AsAtAA={t  t=(t0AtA)}

2.5 序(ordering)关系

如存在uuu使得s⌢u=ts^\smallfrown u=tsu=t,称sssttt的前缀(prefix),同时sssttt≤\leq的序关系:
s≤t=(∃u⋅s⌢u=t)s\leq t = (\exists u \cdot s^\smallfrown u = t)st=(usu=t)
例如⟨x,y⟩≤⟨x,y,x,w⟩\langle x,y \rangle \leq \langle x,y,x,w \ranglex,yx,y,x,w。序关系的性质见课本P24~25。

2.6 长度(length)

ttt的长度记为#t\#t#t,即迹中动作的数目。如#⟨x,y,x⟩=3\# \langle x,y,x \rangle = 3#x,y,x=3。取长度运算的性质见课本P25。

P↓AP \downarrow APA表示#(P↾A)\# (P \upharpoonright A)#(PA),即PPP先投影到AAA上再取长度。

2.7 进程的迹集合(traces)

进程的迹记录了进程尚未执行(⟨⟩\langle \rangle)或从执行开始到任意位置的迹,也就是说它总是从头开始的,用序关系可以很方便的定义进程的迹,例如VMSVMSVMS的迹:
traces(μX⋅coin→choc→X)={s ∣ ∃n⋅s≤⟨coin,choc⟩n}traces(\mu X \cdot coin \to choc \to X) = \{ s \ | \ \exists n \cdot s \leq \langle coin,choc \rangle^n \}traces(μXcoinchocX)={s  nscoin,chocn}
是无限的⟨coin,choc,coin,choc,...⟩\langle coin,choc,coin,choc,... \ranglecoin,choc,coin,choc,...的任意前缀。迹集合具备的性质见课本P28~30。

2.8 进程对迹的after操作

假设s∈traces(P)s \in traces(P)straces(P),可定义P/sP / sP/sPPP在执行完sss定义的一系列动作后的进程。如:
(VMS/⟨coin⟩)=(choc→VMS)(VMS / \langle coin \rangle) = (choc \to VMS)(VMS/coin)=(chocVMS)
after操作具备的性质见课本P32~33。

2.9 符号变换(change of symbol)

符号变换是对迹上每个动作的一一映射,所得到的迹的每个动作会对应于变换前的迹的每个动作。如一个将数值动作翻倍的变换:
double∗(⟨1,5,3,1⟩)=⟨2,10,6,2⟩double^* (\langle 1,5,3,1 \rangle) = \langle 2,10,6,2 \rangledouble(1,5,3,1)=2,10,6,2
注意符号变换的映射带∗^*号时表示对整个迹执行变换,当不带此符号时表示对动作实施变换,也即:
f∗(⟨x⟩)=⟨f(x)⟩f^*( \langle x \rangle ) = \langle f(x) \ranglef(x)=f(x)
下面的性质可加深对此的理解:
f∗(s↾A)=f∗(s)↾f(A)f^*(s \upharpoonright A) = f^* (s) \upharpoonright f(A)f(sA)=f(s)f(A)

2.10 迹内连接(catenation)

如果一个迹内的各个元素也都是迹,则可以定义迹内连接(⌢/^\smallfrown //)将其所有元素按次序连接成一个迹。如:
⌢/⟨⟨1,3⟩,⟨⟩,⟨7⟩⟩=⟨1,3⟩⌢⟨⟩⌢⟨7⟩=⟨1,3,7⟩ ^\smallfrown / \langle \langle 1,3 \rangle , \langle \rangle , \langle 7 \rangle \rangle = \langle 1,3 \rangle ^\smallfrown \langle \rangle ^\smallfrown \langle 7 \rangle = \langle 1,3,7 \rangle /1,3,,7=1,37=1,3,7

2.11 交错(interleaving)

这个词很难翻译,interleaving就是两个迹每次任意选择其一向下执行动作,最后执行完后得到的迹。如:
s=⟨1,2,4,3,5,7,8⟩s=\langle 1,2,4,3,5,7,8 \rangles=1,2,4,3,5,7,8
它可以是下面两个迹的interleaving之一:
t=⟨1,3,5,7⟩,  u=⟨2,4,8⟩t =\langle 1,3,5,7 \rangle , \ \ u=\langle 2,4,8 \ranglet=1,3,5,7,  u=2,4,8

2.12 取迹内元素(subscription)

s[i]s[i]s[i]表示取迹sss的第i+1i+1i+1个元素。书上是用头和尾对其做递归定义:
s[0]=s0∧s[i+1]=s′[i]s[0] = s_0 \wedge s[i+1] = s'[i]s[0]=s0s[i+1]=s[i]

2.13 反转(reversal)

如:
⟨1,2,3⟩‾=⟨3,2,1⟩\overline{\langle 1,2,3 \rangle} = \langle 3,2,1 \rangle1,2,3=3,2,1

2.14 序偶选择(selection)

若迹内元素是一系列序偶(在CSP里表示成x.yx.yx.y的形式),序偶选择s↓as \downarrow asa提取出sss中那些x=ax=ax=a的一系列yyy组成新的迹。如:
s=⟨a.7,b.9,a.8,c.0⟩ s = \langle a.7,b.9,a.8,c.0 \rangle s=a.7,b.9,a.8,c.0
s↓a=⟨7,8⟩s \downarrow a=\langle 7,8 \ranglesa=7,8,而s↓d=⟨⟩s \downarrow d =\langle \ranglesd=

2.15 合成(composition)

✓\checkmark表示进程的成功终止,它只能出现在迹的末尾。则迹sssttt的合成记作s;ts;ts;t,这表示当sss成功终止后才能执行ttt。也就是说✓\checkmark必须出现在sss的末尾ttt才能执行,不存在时要把它补上后ttt才能执行:
(s⌢⟨✓⟩);t=s⌢t        if ¬(⟨✓⟩ in s)(s^\smallfrown \langle \checkmark \rangle);t = s^\smallfrown t \ \ \ \ \ \ \ \ if \ \neg(\langle \checkmark \rangle \ in \ s)(s);t=st        if ¬( in s)
否则ttt不能执行:
s;t=s        if ¬(⟨✓⟩ in s)s;t=s \ \ \ \ \ \ \ \ if \ \neg(\langle \checkmark \rangle \ in \ s)s;t=s        if ¬( in s)
如果✓\checkmark出现在迹的中间部分,那么就将其后面部分都丢弃即可:
(s⌢⟨✓⟩⌢u);t=s⌢t        if ¬(⟨✓⟩ in s)(s^\smallfrown \langle \checkmark \rangle ^\smallfrown u);t = s^\smallfrown t \ \ \ \ \ \ \ \ if \ \neg(\langle \checkmark \rangle \ in \ s)(su);t=st        if ¬( in s)

2.16 迹与产品规格(specification)

迹的引入对定义产品规格起很重要的作用,例如要求贩卖机不亏损的规格:
NOLOSS=(#(tr↾{choc})≤#(tr↾{coin}))NOLOSS = (\#(tr \upharpoonright \{choc\}) \leq \#(tr \upharpoonright \{coin\}))NOLOSS=(#(tr{choc})#(tr{coin}))
即输出巧克力这一动作执行的次数不超过投入硬币这一动作执行的次数。

产品规格用于限制进程,两者间形成满足关系(satisfaction),进程PPP满足规格SSS,记为P sat SP \ sat \ SP sat S

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐