本篇博客是记录MCTK3使用过程中遇到的问题第二弹,有关于MCTK3的介绍以及第一篇的内容见MCTK3使用中遇到的问题
正文内容
1
⟪Γ⟫和⟦Γ⟧策略量词在项目中对应的算子名称为InternalOp.CAN_ENFORCE
和InternalOp.CANNOT_AVOID
,由于断言assert op.numOfOperands() == el.length
的存在且这两个算子的子节点数是根据智能体列表数量变化并不是固定的,即el.length
得到的结果并不是1、2或3那么确定,创建公式时可能会引发断言失败(op.numOfOperands()
返回的是算子op的操作数)。
这一小点是对第一篇中第四点的进一步改进,将env/core/spec/InternalSpecExp.java文件中第17行assert (op.numOfOperands() == el.length)
更改为assert op == InternalOp.CAN_ENFORCE || op == InternalOp.CANNOT_AVOID || (op.numOfOperands() == el.length);
,如下图所示。
2
NNF()函数CAN_ENFORCE(即⟪Γ⟫)和CANNOT_AVOID算子(即⟦Γ⟧)转换问题。
op==Operator.CAN_ENFORCE
和 op==Operator.CANNOT_AVOID
不能简单的按照一元算子处理,这两个算子的孩子节点数组children[children.length-1];
才是子公式,修改如下:
3
在使用GraphStream帮助我们生成证据图中,对于左上角的JToggleButton开关按钮Auto Layout的点击事件,即单击开关启用或禁用状态图的自动布局,当重新启用自动布局时(viewer.enableAutoLayout();
)会出现IdAlreadyInUseException
异常,这是因为每次重新启用布局时, 会将图的所有事件发送回原始图, 该原始图本身已经拥有这些节点和边, 因此会引发IdAlreadyInUseException,规避该问题有两种解决办法,一是在创建viewer实例后再添加节点;二是ViewerPipe实例仅接收与属性相关的事件,即
//将viewer连接回graph, graph成为viewer的接收器, 并且为viewer安装监听器以拦截图形事件.
//返回ViewerPipe管道对象, 该对象作为viewer的事件源
ViewerPipe viewerPipe = viewer.newViewerPipe();
viewerPipe.addViewerListener(this);
//仅接收与属性相关的事件
viewerPipe.addAttributeSink(this.graph);
4
第四点其实算是我添加的一个小功能,实现Ctrl键+鼠标滚轮实现graph图大小缩放。在获取到graph的播放的组件View后,为该组件添加鼠标滚轮滚动事件。
@Override
public void mouseWheelMoved(MouseWheelEvent e) {
double percent = parseDouble(viewPercentText.getText());
//如果鼠标滚轮向上/远离用户旋转, 则为负值; 如果鼠标滚轮朝向用户向下旋转, 则为正值
if(e.getWheelRotation() == 1 && e.isControlDown()) {
//LoggerUtil.info("缩小{}", e.getWheelRotation());
percent += 0.02;
graphJPanel
.getCamera()
.setViewPercent(percent);
} else if(e.getWheelRotation() == -1 && e.isControlDown()) {
//LoggerUtil.info("放大{}", e.getWheelRotation());
percent -= 0.02;
graphJPanel
.getCamera()
.setViewPercent(percent);
} else {
//Toast使用
toast.setMessage("Ctrl键+鼠标滚轮缩放");
}
//viewPercentText.setText(String.valueOf(percent)); //需要保留两位小数
DecimalFormat format = new DecimalFormat("#0.00");
viewPercentText.setText(format.format(percent));
}
5
在env/core/smv/Initiator.java文件,attachPROT(StmtValueArrayWA val)
方法中,
如果这里的this.module_pool[i]是AGENT"main",那么语句this.module_pool[i].getPath()
返回的结果是空字符串""
,最后module_fullname
的内容是".main"
,这显然是不对的,正确结果应是"main"
即可,这里我给出自己的修改意见:
//尝试做以下更改
String module_fullname;
if(this.module_pool[i].getName().equals("main")) {
module_fullname = this.module_pool[i].getName();
} else
module_fullname = this.module_pool[i].getPath()+"."+this.module_pool[i].getName();
6
在多智能体系统建模中(即用的模块关键字是AGENT),Env.pre()函数存在一定问题,以下是改进后的源代码:
private static BDD pred(BDD trans, BDD to, BDDVarSet primeVars) {
BDD prime_to = Env.prime(to);
try {
BDDVarSet actionVars = ATLStarModelCheckAlg.ATLGetAllAgentActionVars();
if(actionVars!=null && !actionVars.isEmpty())
return prime_to.and(trans).exist(primeVars).exist(actionVars);
else
return prime_to.and(trans).exist(primeVars);
} catch (ModelCheckAlgException e) {
e.printStackTrace();
return prime_to.and(trans).exist(primeVars);
}
//return prime_to.and(trans).exist(primeVars);
}
需要说明的是,这份代码仍然不准确,需要后续进一步改进。
问题说明:使用AGENT关键字建模,各智能体的动作变量的带撇(又称加点)版本并不包含在primeVars
中,迁移关系trans
是各状态变量经过某一动作变量至另一状态变量的析取,所以只对primeVars
进行存在量化是不完全的,我在原来代码基础上,再对动作变量actionVars
存在量化,实现如上源代码所示,然而这还是有问题,表现如求解可行状态(feasible states)时,获得的结果并不准确。