系统结构 smv_parser,对smv_parser的结果进行分析
突发性wet,比如水泼了
-> State: 33.7 <-
homePresentState = present
runinfan12.timer = 1
runinfan27.timer = 2
runinfan61.timer = 3
runinalarm.timer = 3
-> State: 33.8 <-
homewater.waterSensor.water = wet
fan.switchCap.switch = off
runinfan12.timer = 0
delayfan12 = 0
runinfan27.timer = 1
runinfan61.timer = 2
runinalarm.timer = 2
-> State: 33.9 <-
homePresent.presenceSensor.presence = not_present
homewater.waterSensor.water = dry
fan.switchCap.switch = on
homewaterState = wet
runinfan27.timer = 0
delayfan27 = 0
runinfan61.timer = 1
runinalarm.timer = 1
对目前状态机的更改问题
实际的运行状态 ⊆ 目前的状态机
1.补全了next
2.加入了对smoke、alarm
如果不加,判断条件就不能是smoke只能是runinfan61.timer=1 & fan.switchCap.switch=on
3.case顺序调换,delay是肯定调后的,状态中runin的调后目前不确定
调换后delayfan修正了,runin虽然没修正但也正常
-> State: 1.22 <-
homePresent.presenceSensor.presence = present
homewater.waterSensor.water = wet
fan.switchCap.switch = off
runinfan12.timer = 1
runinfan27.timer = 0
delayfan27 = 0
runinfan61.timer = 2
-> State: 1.23 <-
homePresent.presenceSensor.presence = not_present
homewater.waterSensor.water = dry
fan.switchCap.switch = on
homePresentState = present
homewaterState = wet
runinfan12.timer = 0
delayfan27 = 4
runinfan61.timer = 1
-> State: 1.24 <-
fan.switchCap.switch = off
homePresentState = not_present
homewaterState = dry
runinfan12.timer = 4
runinfan27.timer = 4
runinfan61.timer = 0
delayfan61 = 0
问题:hold / is true
LTL和CTL的选择问题
快是因为复杂度原因
CTL property不能用LTL替换,比如某些情况是子树,包含多个路径
EF AG这种分析包含多个路径的子树的,只能用CTL,如果最简单的ltl逻辑enough for our purpose,只用ltl就行了
维基上更清楚
https://en.wikipedia.org/wiki/Linear_temporal_logic#Weak_until_and_strong_release
G ((runinfan61.timer = 2 & fan.switchCap.switch = off) -> !( F (runinfan61.timer = 2 & fan.switchCap.switch = on)))
G ((runinfan61.timer = 2 & fan.switchCap.switch = off) -> F (runinfan61.timer = 1 & fan.switchCap.switch = on)),只要找到F不为(runinfan61.timer = 1 & fan.switchCap.switch = on)的就是false,并不能满足我们的需求
!(上式)会出现timer=2并且为on
G,F限制区间问题,read always followed by green or yellow
G(color.red->X(color.green 或 yellow)) ->有当前、未来一步和未来之意?
p->q等价于非p或q
φ ↔ ψ ≡ (φ → ψ) ∧ ( ψ → φ)
->和->F有区别
一个判断当前和后续,一个只判断未后续状态
!一般用于取具体的例子
!G不等于G!
G! (runinfan61.timer=2 & fan.switchCap.switch = off) 全局的每一个状态存在! (runinfan61.timer=2 & fan.switchCap.switch = off)
等价于 !F(runinfan61.timer=2 & fan.switchCap.switch = off)
AutoTap : If @raining while @ rain.off and window.open , then window.close
check_ltlspec -p “G((weather.rain=raining)->!F(window.switch=close))” 基于下一步才变
– Loop starts here
-> State: 1.1 <-
window.switch = open
weather.rain = raining
rain.config = raining
-> State: 1.2 <-
bounded model check就可以避开初始冲突
Trace Type: Counterexample
-> State: 1.1 <-
window.switch = open
weather.rain = not_raining
-> State: 1.2 <-
weather.rain = raining
– Loop starts here
-> State: 1.3 <-
weather.rain = not_raining
-> State: 1.4 <-
Trace Type: Counterexample
-> State: 3.1 <-
window.switch = open
weather.rain = not_raining
step = 1
-> State: 3.2 <-
weather.rain = raining
step = 2
-> State: 3.3 <-
window.switch = close
step = 3
– Loop starts here
-> State: 3.4 <-
window.switch = open
-> State: 3.5 <-
window.switch = close
-> State: 3.6 <-
window.switch = open
MODULE main
VAR
window.switch:{open, close, uncertain};
weather.rain:{raining,not_raining};
ASSIGN
init(weather.rain):=not_raining;
--防止第一次,对没有TAP规则的要注意单独处理一下
--init(window.switch):=close;
next(window.switch):=window.switch;
5种数排列120种
MODULE main
VAR
window.switch:{open, close, uncertain};
weather.rain:{raining,not_raining};
step:1..3;
--rain.config:{raining,not_raining};
ASSIGN
init(weather.rain):=not_raining;
next(weather.rain):=
case
step = 2:raining;
TRUE:{raining,not_raining};
esac;
init(step):=1;
next(step):=
case
step != 3: step+1;
TRUE:step;
esac;
init(window.switch):=open;
next(window.switch):=
case
step = 1:open;
weather.rain = raining:{open, close, uncertain};
TRUE: window.switch;
esac union
case
step = 1:open;
weather.rain = not_raining:{open, close, uncertain};
TRUE: window.switch;
esac;
--check_ltlspec -p "G((weather.rain=raining)->!F(window.switch=close))"
MODULE main
VAR
window.switch:{open, close, uncertain};
weather.rain:{raining,not_raining};
ASSIGN
init(weather.rain):=not_raining;
next(weather.rain):=
case
TRUE:{raining,not_raining};
esac;
init(window.switch):=open;
next(window.switch):=
case
weather.rain = raining:close;
TRUE: window.switch;
esac;
MODULE main
VAR
window.switch:{open, close, uncertain};
window.switch_old:{open, close, uncertain};
window.certain:boolean;
temperature:0..10;
humidity:10..20;
flag_open:0..1;
flag_close:0..1;
ASSIGN
init(temperature) := 5;
init(humidity) := 10;
init(window.switch) := close;
next(window.switch):=
case
next(flag_open)=1 & next(flag_close)=1:uncertain;
temperature < 5: close;
TRUE:window.switch;
esac union
case
next(flag_open)=1 & next(flag_close)=1:uncertain;
humidity > 15 : open;
TRUE:window.switch;
esac;
init(window.switch_old) := close;
next(window.switch_old) := window.switch;
init(flag_open) := 0;
next(flag_open):=
case
temperature < 5: 1;
TRUE:0;
esac;
init(flag_close) := 0;
next(flag_close):=
case
humidity > 15: 1;
TRUE:0;
esac;
init(window.certain) := TRUE;
next(window.certain):=
case
next(flag_open) = 1 & next(flag_close) = 1: FALSE;
TRUE:TRUE;
esac;
-- check_ltlspec -p "G(window.certain=TRUE)"
该路径没有LOOPS
Trace Type: Counterexample
-- Loop starts here
-> State: 1.1 <-
window.switch = close
window.switch_old = close
window.certain = TRUE
temperature = 5
humidity = 10
flag_open = 0
flag_close = 0
-> State: 1.2 <-
temperature = 3
humidity = 17
-> State: 1.3 <-
window.switch = uncertain
window.certain = FALSE
temperature = 0
humidity = 10
flag_open = 1
flag_close = 1
-> State: 1.4 <-
window.switch = close
window.switch_old = uncertain
window.certain = TRUE
temperature = 7
humidity = 13
flag_close = 0
-> State: 1.5 <-
window.switch_old = close
temperature = 5
humidity = 10
flag_open = 0
MODULE main
VAR
window.switch:{open, close, uncertain};
window.switch_old:{open, close, uncertain};
window.certain:boolean;
temperature:0..10;
t1:0..10;
humidity:10..20;
h1:10..20;
flag_open:0..1;
flag_close:0..1;
step:1..3;
ASSIGN
init(temperature) := 5;
next(temperature):=
case
step = 1: 3;
TRUE:0..10;
esac;
init(humidity) := 10;
next(humidity):=
case
step = 1: 17;
TRUE:10..20;
esac;
--等于配置初始值
init(t1) := 5;
--第一次变化之后保持不变,防止生成过多无效空间
next(t1):=
case
step = 1: 1..10;
TRUE:t1;
esac;
init(h1) := 15;
next(h1):=
case
step = 1: 10..19;
TRUE:h1;
esac;
init(step):=1;
next(step):=
case
step != 3: step+1;
TRUE:step;
esac;
init(window.switch) := close;
next(window.switch):=
case
next(flag_open)=1 & next(flag_close)=1:uncertain;
temperature < t1: close;
TRUE:window.switch;
esac union
case
next(flag_open)=1 & next(flag_close)=1:uncertain;
humidity > h1: open;
TRUE:window.switch;
esac;
init(window.switch_old) := close;
next(window.switch_old) := window.switch;
init(flag_open) := 0;
next(flag_open):=
case
temperature < t1: 1;
TRUE:0;
esac;
init(flag_close) := 0;
next(flag_close):=
case
humidity > h1: 1;
TRUE:0;
esac;
init(window.certain) := TRUE;
next(window.certain):=
case
next(flag_open) = 1 & next(flag_close) = 1: FALSE;
TRUE:TRUE;
esac;
-- check_ltlspec -p "G(window.certain=TRUE)"
Trace Type: Counterexample
-> State: 1.1 <-
window.switch = close
window.switch_old = close
window.certain = TRUE
temperature = 5
t1 = 5
humidity = 10
h1 = 15
flag_open = 0
flag_close = 0
step = 1
-> State: 1.2 <-
temperature = 3
t1 = 1
humidity = 17
h1 = 11
step = 2
-- Loop starts here
-> State: 1.3 <-
temperature = 0
humidity = 10
flag_close = 1
step = 3
-> State: 1.4 <-
temperature = 1
humidity = 12
flag_open = 1
flag_close = 0
-> State: 1.5 <-
temperature = 0
humidity = 10
flag_open = 0
flag_close = 1
反例
一、线性时序逻辑(LTL)
X,U是temporal operator,不指precise time
W(weak until) (ψ U φ) ∨ G ψ 多了个G ψ
F sometimes
FG infinitely often
Realse ψ R φ。φ保持为真,直到ψ变为真(包括为真的地方)。如果ψ不会为真,则φ一直为真
the syntax of LTL
之前都是看the first letter就行
X可以看the rest of word
X(X(p2))
X(p1Up2) 在下一状态,p1Up1 = true?和p1Up2的区别是起始位置不同
X(X(p1UX(p2)))
p1 until p2 ,找到p2为true的第一个地方,在那个地方前p1 is true
true每个点都满足意味着没约束,true U p1 在某个p1为true的地方
true U ¬p1 在某个p1为flase的地方
¬(true U ¬p1)意味着无法找到某个p1为flase的地方,everywhere p1 is true
∅1→∅2 如果∅1,那么∅2
i can’t(¬) reach F(¬∅) sometime
G§:p is True in every state
每处F(∅)为true
LTL本身的定义和在状态机中的体现
AP-INF是所有可能,property ∅是AP-INF的一个子集,Words(∅):AP-INF中满足∅的words
一个是对符号的拆分一个是satisfy ∅,对复杂的直接把∅替换为一坨
words(∅) = σ
狼羊过河问题
planning problem:find a path to the goal state
check !∅,如果有反例是满足∅的
MODULE main
VAR
man:boolean;
goat:boolean;
wolf:boolean;
cabbage:boolean;
carry:{g,w,c,0};
ASSIGN
init(man) := FALSE;
init(goat) := FALSE;
init(wolf) := FALSE;
init(cabbage) := FALSE;
init(carry) := 0;
--man要么在左边要么在右边
next(man) := {TRUE,FALSE};
--man和其它同值则可以搬运,且一次可以搬运的选项是非确定性(non-deterministic),esac union 提供了next value的non-deterministic choice
-- carry并不是实际的,只是提供了一种选项(choose to do),因为可以呆在原地不变
next(carry) := case
man = goat:g;
-- 确保condition exhausted
TRUE:carry;
esac union
case
man = wolf:w;
TRUE:carry;
esac union
case
man = cabbage:c;
TRUE:carry;
esac union 0;
next(goat):= case
-- 如果goat被carry,那么反置值表示达到另一岸
--next(carry) = g:!goat;
-- carry = goat但man可能呆在同一岸,随着人的位置而变化
next(carry) = g:next(man);
TRUE:goat;
esac
next(wolf):=
next(cabbage):=
next
LTLSPEC
!( ((goat = cabbage | goat = wolf)->man = goat) U (man & cabbage & goat & wolf) )
nusmv test.smv
trace相关的p94 - 100
4个变量和转化为可达性问题(全0到全1)
二、分支时序逻辑(CTL)
每个node可以是{p1}{p2}{p1,p2},如switch=ff & present = off
LTL讨论path的property
CTL讨论tree的property,一个状态机可以表示为一颗树,初始状态是根节点
E
红点并不是node,而是该node有对应的ap
A
两个符号E代表Exist,Exist a path 满足∅,A代表all path满足∅,E(F(A(G(∅)))),某个子树满足A(∅)
E mix with A
CTL*
state formulae
path formulae
LTL CTL* CTL的关系
如果系统满足LTL,则对应的树满足A(∅),LTL属于CTL的一部分
CTL property不能用LTL替换,比如某些情况是子树,包含多个路径
LTL不能用CTL实现,CTL也不能用LTL实现
如果最简单的ltl逻辑enough for our purpose,只用ltl就行了
CTL是CTL*限制后的
LTL CTL*的转换
如果G (runinfan61.timer=2 & fan.switchCap.switch = off),如果等于初始0,找到反例并不能说明冲突存在
–LTLSPEC G! (runinfan61.timer=2 & fan.switchCap.switch = off)
如果找到反例则说明这种情况存在