OO第三单元作业总结

OO第三单元作业:JML与架构设计总结
本文是OO第三单元作业总结,介绍了JML语言的理论基础和应用工具链,如openjml、jmlunitng的使用。阐述了三次作业的架构设计,包括用ArrayList存储、Floyed和Dijkstra算法求最短路径等。分析了第三次作业的bug原因,强调算法和整体架构设计的重要性。

OO第三单元作业总结

1. JML语言

理论基础、应用工具链情况

(1)jml表达式

使用JML的话,我们就能够描述一个方法的预期的功能而不管他如何实现,让我们最开始能尽量从面向对象的角度进行编程,最先去关注整体的设计,再去关注具体方法的实现。

JML引入了大量用于描述行为的结构,比如有模型域、量词、断言可视范围、预处理、后处理、条件继承以及正常行为(与异常行为相对)规范等等。

相关语法主要有

1.requires 前置条件

2.assignable 可以修改的成员的属性

3.ensure 后置条件

4.\result 方法执行后的结果

5.\old 在方法执行的取值

6.\max 最大值

7.\min 最小值

8.\num_of 总数量

9.constraint 状态变化约束

10.invariant,定义了一个方法的不变的属性

......

(2)jml应用工具链

我们最主要使用的是openjml,其功能如下
1615444-20190522175156014-1641109241.png

下面我就openjml的使用进行一个简单的演示。

public class Sub {
     //@ requires a > 0;
     //@ requires b > 0;
     //@ ensures \result == a-b;
     public static int sub(int a, int b){
         return a-b;
     }

    public static void main(String args[]){
         System.out.println(sub(2,3));
     }
 }

(1)java -jar openjml.jar -check Sub.java

我们可以看到,没有报错信息。

我们尝试去掉@ ensures \result == a-b;的分号,可以看到报错结果如下1615444-20190522175601572-1500759981.png

(2)openjml -rac Sub.java

现在,我们尝试增加一个后置条件@ensures \result>0;

由于2-3<0;明显不符合result>0的要求。

在运行中,我们可以看到如下报错
1615444-20190522175755661-743224790.png

当然,对于jml的验证工具不止于此,jmlunit也是一个非常好用的工具。

下面就让我们一起来看看JMLUnit的使用。

2. JMLUnit测试

我用jmlunitng对第一部分的Sub进行了简单的测试,首先,我进行编译生成的目录树如下图
1615444-20190522180127095-1215392536.png

再用Sub_JML_Test进行测试,测试结果如下:
1615444-20190522180221575-846776656.png

我们可以看出,该测试对各种边界条件都进行了很好的测试。

我们再加上加法指令,效果如图
1615444-20190522180310484-625711496.png

在此,就暂时不对更复杂的情况进行举例了。

3.架构设计

(1)第一次作业

要求我们完成MyPath,继承Path接口,因为实现的过程非常简单,我主要使用了Arraylist对path和pathid进行存储因此就不过多赘述了。在第一次作业中,我也使用了缓存,对于查找类的指令,在第一次查找之后,可以把结果存储。

1615444-20190522174657723-37058192.png

(2)第二次作业

第二次作业最关键的部分是shortest Path的实现。我的做法是采用Ffloyed进行图的构建,在每次有对图进行修改,如加入路径,删除路径时,重新进行图的构建。此做法复杂度是o(n3).但是之后我进行反思,觉得对于稀疏图来说,dijsktra更具有一定优势,对于单源最短路径,复杂度为o(eloge).

我的设计是让MyGraph直接继承MyPath类来实现Graph接口,然后再去实现containsNode, containsEdge, getShortesetPathLength......对于遍历得到的路径,我们用二维数组将它存储起来,下次查询时利用该结果。

而最短路径的查询,我将它放到了isConnected方法中,这样既能直接判断是否连通,也能构建好最短路径。

由于此次不太复杂,所需遍历次数根据指导书给的要求只需要250*250*20次遍历,显然不会超时。
1615444-20190522180534394-23759343.png

(3)第三次作业

对于第三次作业的计算,我使用的dijsktra,我们可以观察到,无论是求最低票价,最少换乘,最高满意度,路径的计算,我们都可以用相同的方法,只是权值不同。因此我设计了一个calculator类,用于路径权值的计算(如下图)

1615444-20190522180834782-776226213.png
1615444-20190522180914262-1283157690.png

我还设计了一个静态方法Algrithom类,专门用于dijsktra算法,每次调用时传入calculator和相关的一些变量,进行计算。这样,代码的利用率会变高。

第三次作业的大致框架还是基于前两次作业,甚至,大部分基础的东西都没有进行改动。这次作业的难点是判断换乘。我最初的想法有很大漏洞,导致强测直接只过了2个点,但现在回想,其实在不追求一定最小的情况下,性能其实是不错的,但可能会在一些换乘点判断错误。我最初的想法是,对于每一条遍历生成的path记录一个路径上第一个点的fromPath和最后一个点的toPath。比如对于对于遍历中找到的最优解temppath1:[1,2,3,4],其中1在path1上,4在path2上,我们对此记录下(1,2),当遇到新的符合的边时(假设这儿为[4,9,14])其中4在path4上,14在path3上。显而易见,这儿就需要经过换乘,因此加上换乘代价。我将这个方法交到第二次作业的测评机上去跑,并且使每次path的遍历都去判断换乘。在简单的情况下,性能差异不大,但在复杂的情况下,大概用时是上次的1.5倍左右。(非常可惜这个方法只能求得局部最优解),在设计使我也没能思考到在算(1,4)的路径时我就已经把frompath和topath的id固定了,可能下一条路径从另外一条路径经过3后,接下来的点是不需要换乘的,但在这儿就固定了1-3只能是走这条最短路径。

在看到强测爆炸之后,我又看到了拆点法,即每条路径上的点看做是不同的点。这样就相当于是一个单纯的dijsktra问题。在计算完成时,我们再通过遍历结果,对相同的点进行合并。我的重构即采用这种方法,我使用了HashMap对点的原始id和虚拟id进行对应。但是经过尝试,该算法速度太慢,比如在多个点重合的情况下,需要遍历的边数极具增加,但是,该方法的正确性是能够得到保证的。

我在评论区看到一个方法也觉得挺好--分层floyed(https://course.buaaoo.top/assignment/75/discussion/216)。还有一种能减小复杂度的方法就是,对于换乘建立的虚点,让他们只与同站虚点相连,不与实点相连,这样也能减少边的条数,对于dijsktra非常有利。

4.bug以及修复情况

在第一二次作业中均没有bug,第三次由于算法的问题导致只过了两个点。

错误原因为:利用了前面算出的局部最优解,而当时没考虑到这只是一个局部最优解(关于这部分,上文已经有比较详细的描述)

而在互测中,我发现常见的bug类型有:

  1. 超时。第三次作业尤其明显。
  2. null pointer,多出现remove之后
  3. 计算错误。这一般是算法出现的纰漏。
  4. 边界情况产生的错误。比如一个图里没有东西,但执行指令时并没有判断null的请况,导致出现错误。

5. 心得体会

这次作业一二次作业都很简单,非常易于设计,只要读懂jml,不出重大问题,几乎全部通过。
但对我们的设计模式进行了很大的考验。
首先,是算法,拥有一个正确、快速、稳定、可维护的算法至关重要。
其次,我们的整体架构,如类的确定,继承和重写,也对结果和设计难度有很大影响。
在整个作业中,jml实现了整体的架构,我们也可以尝试在以后的作业中,先去面向对象,把整体的类和架构实现,再去面向过程,细致的去考虑高效的实现算法。

转载于:https://www.cnblogs.com/xjm1999/p/10907499.html

一、数据采集层:多源人脸数据获取 该层负责从不同设备 / 渠道采集人脸原始数据,为后续模型训练与识别提供基础样本,核心功能包括: 1. 多设备适配采集 实时摄像头采集: 调用计算机内置摄像头(或外接 USB 摄像头),通过OpenCV的VideoCapture接口实时捕获视频流,支持手动触发 “拍照”(按指定快捷键如Space)或自动定时采集(如每 2 秒采集 1 张),采集时自动框选人脸区域(通过Haar级联分类器初步定位),确保样本聚焦人脸。 支持采集参数配置:可设置采集分辨率(如 640×480、1280×720)、图像格式(JPG/PNG)、单用户采集数量(如默认采集 20 张,确保样本多样性),采集过程中实时显示 “已采集数量 / 目标数量”,避免样本不足。 本地图像 / 视频导入: 支持批量导入本地人脸图像文件(支持 JPG、PNG、BMP 格式),自动过滤非图像文件;导入视频文件(MP4、AVI 格式)时,可按 “固定帧间隔”(如每 10 帧提取 1 张图像)或 “手动选择帧” 提取人脸样本,适用于无实时摄像头场景。 数据集对接: 支持接入公开人脸数据集(如 LFW、ORL),通过预设脚本自动读取数据集目录结构(按 “用户 ID - 样本图像” 分类),快速构建训练样本库,无需手动采集,降低系统开发与测试成本。 2. 采集过程辅助功能 人脸有效性校验:采集时通过OpenCV的Haar级联分类器(或MTCNN轻量级模型)实时检测图像中是否包含人脸,若未检测到人脸(如遮挡、侧脸角度过大),则弹窗提示 “未识别到人脸,请调整姿态”,避免无效样本存入。 样本标签管理:采集时需为每个样本绑定 “用户标签”(如姓名、ID 号),支持手动输入标签或从 Excel 名单批量导入标签(按 “标签 - 采集数量” 对应),采集完成后自动按 “标签 - 序号” 命名文件(如 “张三
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值