我是靠谱客的博主 忐忑老鼠,最近开发中收集的这篇文章主要介绍simulink中if模块_Simulink与圈复杂度,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

ebbf43c05d9f3a519702aad07f4a2624.png

若干年以后,由于转行或者不再做技术等原因,你可能已经记不太清楚之前费尽千辛万苦习得的各种技术细节;但是,最终你会发现:依然有很多宝贵的概念留存并沉淀于脑海深处(比如中学课本中的某些物理概念)。

今天来一起了解下:基于模型开发中,一个非常重要的概念---圈复杂度

1,圈复杂度

simulink官方文档定义如下:

4e5f32b563fc7b99d200ec6c002dd311.png
Fig1 圈复杂度定义

读起来,会不会有点懵圈呢?

没关系。后面会逐步进行解释。

首先圈复杂度可以用来衡量单元模型结构复杂程度。

圈复杂度越高,说明模型越复杂,可测性就越差,那么相对来说也更容易出问题。

如果你设计过相对复杂的逻辑,可能体会更加深刻一些,因为它真的容易出错啊。

因此,这也给我们一些警示:

作为软件架构工程师,需要合理划分软件单元。不能让某个单元过于复杂,以至于难以测试。

作为模型开发者,应该尽量使用更简洁的方式搭建或者表达模型(别忘了美国程序员因无法忍受同事代码不规范而枪杀4名同事的疯狂事迹)。这就需要在软件需求分析方面多下功夫:用心解读软件需求,并弄清楚其内在的逻辑性和关联性。

2,Simulink如何计算圈复杂度?

那么simulink中,圈复杂度是如何计算的呢?

按Fig1 中定义的公式:

其中N代表判定分支节点的个数,

代表第n个分支节点可能的输出结果数目。

需要指出,if else 、switch case 、 for/while循环等,都属于一个判定分支节点。

2.1,switch模块

9a68dedb039812e3577f0eff30a375cf.png
Fig2 switch 逻辑

对于该子系统,只存在一个判定节点,即switch模块(其生成代码后就是一个if else语句呀),且该模块输出只有两种可能,即true or false。

因此圈复杂度为:

覆盖度报告中给出的圈复杂度结果也为1,如下图:

1a168c359eab11c879483bca8e1b59fa.png
Fig3 覆盖度报告中圈复杂度

可以看出,simulink计算的圈复杂度和圈复杂度原始的概念定义存在一些差别。

维基百科:圈复杂度由Thomas J. McCabe, Sr.于1976年提出。圈复杂度大小可以表示为判定分支节点数目加1。按照这个原始定义的话,switch模块的圈复杂度应该为1+1=2。注意这点区分就行了。

2.2,Multiport Switch模块

bc7208a25395ecc847067245068fadc9.png
Fig4 multiport switch 逻辑

对于该子系统,只存在一个判定分支模块,即MultiportSwitch模块(生成代码后就是switch case语句呀),而且这个分支模块输出只有4种可能,即inport2,inport3,inport4或inport5。

圈复杂度为:

和覆盖度报告中提供的结果相等,如下图:

56c91a8d204ba4fe6a73570a674339ec.png
Fig5 覆盖度报告计算结果

2.3,stateflow流程图

b0d55e6d66afb68c3abf1ba8a9fc997d.png
Fig6 stateflow逻辑流程图

可将for循环看作一个判定模块,共有三个判定分支模块,每个判定节点均有两种结果(true or false)。

覆盖度报告中的计算结果如下图,和上述计算结果相同:

2eeb2bb54aa0ec44d641e37e0298ee8d.png
Fig7 覆盖度报告中圈复杂度

那为什么stateflow内部逻辑的圈复杂度结果为3,而整个stateflow子系统的结果却为4呢?

见圈复杂度定义Fig1:对于stateflow模块或者原子子系统,需要额外加1。


那么,Fig 8中模型的圈复杂度为多少呢?

29f4af8c9b16eb555069ffd3f46fff21.png
Fig8 复合条件

有人认为,它是3,其实也不错,这是由原始的圈复杂度定义所得出的结果。

simulink却定义它仍然是1,如下图:

eefe977e5f8e93ac0894dc8fd22ba97a.png
Fig9 Simulink中圈复杂度

这也是simulink中的圈复杂度定义与已有圈复杂度定义的区别之处:simulink中,它仅仅和判定分支覆盖(Decision)概念相对应,和条件覆盖(Condition)没有必然联系。

至于Decision/Condition/MCDC覆盖之间的区别,我们后面再讨论。

3,降低圈复杂度

好了,说了这么多,目的不就是想降低圈复杂度吗?

该如何做呢?

我这里仅仅举一个简单的例子,以抛砖引玉。如果大家有好想法(可以降低圈复杂度),欢迎评论区讨论。

由前述分析可知:如果能降低判定分支数目,那么也就能降低圈复杂度。

举例如下。

Simulink模型为:

61c151a36a74b9b43c6babadb7098140.png
Fig10 模型举例

case合并前的逻辑为:

function out = unmerge(input)
switch(input)
    case 1
        out=2;
    case 2
        out=4;
    case 3
        out=6;
    case 4
        out=10;
    otherwise
        out=100;
end

case合并后的逻辑为:

function out = merge(input)
switch(input)
    case {1,2,3}
        out=input*2;
    case 4
        out=10;
    otherwise
        out=100;
end

执行仿真,获得case合并前后的圈复杂度及判定覆盖度(分支覆盖度)对比结果,如下图:

676d49b284b04ba21257f431d70599b3.png
Fig11 圈复杂度及判定覆盖度对比

可知,合并case后,圈复杂度从6降低为4,基于同样的测试案例输入(见下图),合并后的matlab function 判定覆盖度已经达到100%;而未执行合并的判定覆盖度仅为67%,需要提供更多的测试输入才能达到100%覆盖。

a3b6caaab5132658fb2b42bbb7492243.png
Fig12 测试案例输入

可知,圈复杂度降低,使得逻辑更加简洁的同时,也可以提高测试效率(让测试更简单)!!!


不足之处,希望大佬们不吝指出。

如果本篇文章对你有些帮助或者启发,记得点赞哦。

你也可以关注我的公众号:土人很土。

参考文献:

1,matlab官方帮助文档

2,圈复杂度原理和实践

最后

以上就是忐忑老鼠为你收集整理的simulink中if模块_Simulink与圈复杂度的全部内容,希望文章能够帮你解决simulink中if模块_Simulink与圈复杂度所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(60)

评论列表共有 0 条评论

立即
投稿
返回
顶部