标签:循环 人物 和我 lock lan tle 不能 返回 图论
你以为你学的是JML,你以为你在学规格,你以为你上的课程叫OO。
哦,这些都没有错。
什么程序不能掺点算法题呢?\-_-/
JML(java modeling language)是一种描述代码行为的语言,包括前置条件、副作用等等。JML是一种行为接口规格语言 (Behavior Interface Speci?cation Language,BISL),基于Larch方法构建。
通过使用JML,我们可以忽略一个类、一个方法内部的具体实现,专注于描述方法的预期功能,从而把过程性的思考延迟到方法设计中,扩展了面向对象设计的原则。
总结来说,JML是一种用于规格化程序设计的辅助工具。
JML是一种行为界面规范语言(BISL)。在这种被称为面向模型的编程风格中,我们需要指定方法或抽象数据类型的接口及其行为。
方法 或 类 的接口是从程序的其他部分使用它所需的信息。对于JML,这是调用方法或使用属性或类所需的Java语法和类型信息。
方法 或 类 的行为描述了一组能够执行的状态转换:定义调用方法的一组状态,允许方法可以赋值的一组属性,以及调用状态和返回状态之间的关系。
翻阅JML的网站,会发现JML的工具有很多,洋洋洒洒至少也是10余种。可是仔细观察,其中大多数是对于老版本Java的支持。其实我们现在可能能用上的,就是OpenJML
和JMLunitNG
。
读取JML书写的方法逻辑,运用SMT Solver
对方法进行验证。
针对书写的JML规格,生成看似很强的数据用于测试。
一句话总结:遇到传奇error。
听说是Java版本问题。经过了将近1天的努力,我最终决定,为了不乱改环境(毕竟还有一个单元作业),选择了放弃。
当然我还是通过各种方式去了解了一下这些工具的使用效果的。
OpenJML
来说,根据往届学长们的博客,这个工具并不支持\forall
、\exist
等部分语句。显然少了循环体,根本无法完成对本单元所要用到的方法的规格化声明。JMLunitNG
则是会倾向于设计一些极端数据。这些极端数据是对于计算机,或者说是语言本身设计的,比如去检查int
变量是否会越界之类的问题。各种方面来说,JML都是不成熟的。当然这也反应着其不易用性。在现在的环境下,JML竟然连新版本Java环境都不支持,其官方手册最后一次更新也是2年前。在如今计算机领域飞速发展的大环境下,JML没有前进便必然被淘汰。
当然,虽然其工具链并不好用,其本身进行一些规定形成一种注释或是设计用的风格还是很值得借鉴的。
本单元作业的架构实在是没有什么值得一说的地方,毕竟有什么类、每个类有什么方法都已经被JML定义好了,全年级的同学的程序的架构恐怕都是一样的。要说不同就是实现方式的不同了。
就个人来说,本单元作业自己的设计思路完全是性能驱动,究其原因是课程组发布的说明里面总是跟着这么一句话:
“程序的最大运行cpu时间为2s,虽然保证强测数据有梯度,但是还是请注意时间复杂度的控制。”
其实也没必要说得这么委婉……反正就是卡(kao)性(suan)能(fa),说明白了没啥不好的。
初来乍到看JML给的要求的时候,直观感觉是:直接照着JML写,问题不大,性能对于这次的测试其实也足够了。但终究还是有一些调整。
Person
类的规格,怎么看怎么觉得存关系(acquaintance
和value
)的两个数组很丑陋,因此改变了固定数组的存放,变为HashMap
容器,Key
存放相关者的ID,Value
存放ID对应的value
。isCircle
了。HashMap
,Key
存放人的ID,Value
存放HashSet
,内部存储与此人相关联的人的集合;HashSet
合并,并改变前述HashMap
。这次作业的工作重心倾向到了Group
这个新加的类之中。组和图的概念在本单元作业里面出现了并行,有点意外。难度主要集中在queryGroupRelationSum
、queryGroupValueSum
、queryGroupAgeMean
、queryGroupAgeVar
这四个方法上。整体来说,还是为了性能,我取出来了实现并查集的一部分思路——进入更新。每有一个人加入组中,对保存的属性进行更新。
queryGroupRelationSum
、queryGroupValueSum
queryGroupAgeMean
、queryGroupAgeVar
来了来了,图论的东西它来了。
delFromGroup
queryBlockSum
HashMap
,存放人物ID与其所在集合的对应关系,遍历其中集合有几个便可。但遍历操作无疑复杂度还是高,因此延续运用进入更新想法,设置新属性,每次增加人和增加关系时对这一属性进行更新,复杂度降为1.queryMinPath
PriorityQueue
容器了,不用白不用。当然我事后觉得幸好优化了……我不应该因为这是OO课就对课程组的善良抱有希望……queryStrongLink
HashSet
,也算是进行了一些优化。主要问题出在isCircle
对应的HashMap
的更新上,由于并不是完全按照并查集实现,每次更新需要遍历操作。
这个Bug是自己课下写的时候直接通过“脑内模拟”感觉出来的……
强测和互测都没有翻车。
第一次强测挂零。
第一次没进互测。
嘛……什么事情都要经历一下是吧……
assert(…)
,但自己对Java中assert(…)
的行为理解不到位,(事实上这句话就和没写一样……)所以该错还是错了。其实谈不上Bug,因为自己对tarjan算法的理解问题,自己写的queryStrongLink
一直无法正确实现目的。充分理解算法之后就没有问题了。
强测和互测没有翻车。
规格化设计是必要的。规格可以让多个人写一个程序的时候,进行很好的分块化处理,方便大家进行交流,方便程序各部分的交互,方便对各部分进行分开测试。
当然,对于个人来说,规格就像是书写良好的注释,提醒自己各部分要干什么,提醒自己哪里可能存在bug。
然而,想要写好规格很难,因为自己会有许多先入为主的设想。想要写出充分条件可能还较方便达成,但规格要求的是写充分必要条件。想要书写良好的规格,需要多加练习。
JML是一个用于对于Java进行规格化设计所用的语言。作为一个语言,它本身算是优秀,虽然有时候括号很多看着不方便,但其进行了严格定义,每种语句本身不会有语义偏差——除非写的不好。
但是其工具链可以说处于不可用状态。
当然我们也需要思考其本身需不需要强大的工具链。毕竟再细化下去,JML就已经不是起到辅助作用,而是可以单独作为一种语言了。
这是一点碎碎念了。最后一次官方给的数据来看,同学们的CTLE错误率已经到达了50%。这真的是面向对象课程嘛……最后摆明了考算法……
当然在前言也说了,什么程序设计用不到算法呢?在这里最多也就吐吐苦水爽一爽。
但有一件事情是值得关注的。测评机真的不稳定。
这很正常,任何一块CPU同时运行多道程序,其每个程序自身速度都会降低。
所以集中所有人进行强测的时候,很多人出现了CTLE。
室友A和我本地对拍时候程序运行时间跟我基本一致,强测CTLE一点,该点数据本地自测跑出来的速度跟我还是差不多。Bug修复也是直接交源代码AC。
在这里也是想,万一自己博客荣幸滴被后辈阅读,一定要把程序各处优化到最好,然后听天由命……
标签:循环 人物 和我 lock lan tle 不能 返回 图论
原文地址:https://www.cnblogs.com/Suxy-99/p/12939472.html