Petri Net入门
前段时间有朋友问了关于Petri Nets相关的程序问题,就花了点时间学习了下,因此本文是Petri Nets自学入门过程中的总结。因为当时只关注程序设计上的问题,所以是比较基础的内容,不会涉及到数学和程序上的内容。
看懂Petri Nets

先解释下这个图中的元素:
- Place(P):蓝色的圆
- Transition(T):黄色的方形
- Arc(A):红色的连线
- Weight(W):Arc上的数字,如果没有写,则为1
- Token:紫色的圆
其中Arc只能连接Place和Transition,也就是下面这种情况是不允许的:

Token只存在Place中,理论上来说一个Place中可以存储的Token是没有上限的(当然也可以根据需求做限制)。
当Transtion的入口所有Place都满足条件(即Place种的Token数量不少于Weight),以及出口的所有Place都满足条件(即Place种的Token数量加上Weight的数量不能超过Place本身允许的Token数量上限),那么称这种情况为Fireable。当满足Fireable时,就可以进行Fire,Fire就是从Transition的入口所有Place移除对应Weight数量的Token,同时在Transition的出口Place中添加对应Weight数量的Token。
以例图来说:T1的Fire条件是P1中至少有1个Token,因此Fire之后:

T2的Fire的条件是P2中至少有2个Token,但现在P2中只有1个,因此不能Fire。而T1的Fire条件仍然满足,因此T1执行Fire之后:

此时T2的Fire条件已经满足,因此T2执行Fire之后,会生产2个Token:

另一个例子

可以看到T1的Fire条件是满足的,Fire后T1会生产1个Token到P2:

此时P2有2种选择,因为T2和T3都是Fireable(当有多个Transition都是可以Fire时,可以使用不同的策略),假设选择T3,那么T3会生产1个Token给P1,同时生产1个Token给P3:

死锁
当Petri Net中没有可以Fire的Transition时,这时就进入了死锁,因此设计Petri Net的时候需要尽量避免这种情况,比如这种情况:

最终会变成没有任何一个Transition可以进行Fire:

画一个生产者消费者模型
最简单的一个生产者消费者模型:
生产的条件:允许生产
消费的条件:允许消费并且生产完成

同时T(生产行为)的下一步就是P(产品生产完成),而T(准备消费产品)的下一步就是P(消费产品),而消费产品后就可以重新消费,同时可以重新开始生产:

最后就是初始的触发条件了,需要能够让状态动起来,可以看到需要在P(可以生产) 和 P(可以消费)各自放入一个Token::

代码实现
一个基于java的Petri Net实现:https://github.com/iyichen/petri-net