Measuring Code Behavioral Similarity for Programmingand Software Engineering Education

测量代码行为相似性用于编程和软件工程教育

基本信息

博客贡献人

糖瓶

作者

Sihan Li,Xusheng Xiao,Blake Bassett,Tao Xie,Nikolai Tillmann

摘要

近年来,通过信息技术进行的在线编程和软件工程教育极大流行。热门课程往往有数百或数千名学生,但只有少数课程工作人员。所以需要工具自动化来维持教育质量。在本文中,我们认为量化程序之间行为相似性的能力有助于编程和软件工程的教学与学习,并提出三种指标来近似计算行为相似性。具体而言,我们利用随机测试和动态符号执行(DSE)来生成测试输入,并在这些测试输入上运行程序来计算行为相似性的指标。我们在Pex4Fun平台上的三个真实世界数据集(到目前为止已积累超过170万次游戏互动)上评估了我们的指标。结果显示,我们的指标提供了对行为相似性的高度准确近似。我们还展示了我们指标的多项实际应用,包括提示生成、进度指示和自动评分

1. 引言

近年来,随着信息技术的进步,在线编程和软件工程教育获得了极大的关注。入门编程课程是大规模开放在线课程(MOOC)中最受欢迎的课程之一。许多MOOC提供商,如edX、Coursera和Udacity,都提供了编程和软件工程课程,其中有成千上万名来自世界各地的学生注册。除了MOOC,其他形式的在线编程和软件工程教育也吸引了大量关注。例如,Pex4Fun ,以及其最近的继任者Code Hunt,是用于通过游戏教学和学习编程的在线教育平台。到目前为止,Pex4Fun平台已积累了来自世界各地的玩家超过170万次游戏互动。

在线编程和软件工程教育的一个挑战是让大规模班级维持教育质量。通常,热门课程往往有数百甚至数千名学生,但只有少数课程工作人员。工作人员数量有限会给提供高质量教育带来挑战。对教师来说,许多任务,如评分和为编程作业提供定制反馈,需要教师审阅和理解学生的代码。这些任务的工作量是灾难性的。然而,跳过或延迟此类任务会阻止教师跟踪学生的表现。对学生来说,他们很难从教师那里获得及时、定制的反馈和帮助。虽然学生可能从同学那里寻求帮助,但同学在许多情况下往往无法提供帮助或有价值的反馈。老师或同学无法总是坐在学生身边,学生在编码时遇到问题时也无法提供及时的提示。

为了缓解这个问题,我们提出使用工具自动化来减少教师在教学过程中的负担,并改善学生在编程和软件工程课程中的学习体验。我们认为自动量化程序之间行为相似性的能力在许多方面都有帮助。例如,它可以帮助教师评估学生的程序。学生程序与样本解决方案程序之间的行为相似性可以作为评分的一个因素。更高的相似性通常意味着更高的分数。此外,它可以用作学生编码过程中的进度指示器。我们的工具自动化可以不断计算并显示学生当前程序与解决方案程序之间的行为相似性,以便学生跟踪他们的进度。学生取得的一系列增加的相似性分数表明学生正在向解决方案前进,而显著下降可能表明学生正在以错误的方式修改代码或恢复正确代码。此类信息可以帮助学生及早意识到潜在问题并避免进一步偏差。而且,行为相似性还可以用于检测不同学生之间相似的程序。当学生在某些任务上需要帮助时,这些来自其他学生的相似程序可以用于生成下一步的提示。我们在第6节中详细描述了此类广泛应用。

然而,一般来说,精确量化行为相似性具有挑战性。理想情况下,两个程序之间的行为相似性可以通过计算在两个程序上产生相同输出的输入(称为一致输入)比例来衡量,该比例相对于整个输入域。一个直接的方法是枚举输入域中的所有输入,并在两个程序上运行每个输入以比较输出,但对于具有大型或无限输入域的程序来说,这种方法是不可行的。为了实际测量行为相似性,我们提出在程序上运行代表性输入而不是所有输入,基于两个见解来近似它们的行为相似性。第一个见解是通过从输入域中均匀采样显著部分的输入,基于采样输入计算的行为相似性可以提供对实际行为相似性的良好近似。第二个见解是,使用能够测试不同程序路径的输入作为代表也可以提供良好的近似,因为这些不同的程序路径通常代表不同的程序行为。动态符号执行(DSE)是一种技术,它同时符号和具体地执行程序,以从分支中收集约束,并系统地否定收集约束的部分来生成新的程序输入。随着强大的约束求解工具的出现,DSE 在生成实现高代码覆盖率的测试输入方面显示了有前景的效果。我们可以利用 DSE 来系统地生成高覆盖率的测试输入,并使用生成的测试输入来高效探索程序路径。

基于这两个见解,我们提出了三种使用测试生成技术来测量行为相似性的指标。我们的第一个指标,随机采样(RS),是通过使用随机测试生成来生成均匀分布在输入域上的输入来计算的。然后,我们在每个测试输入上分别运行两个程序以比较它们的输出。一致输入在采样输入中的比例就是RS的值。第二个指标,单程序符号执行(SSE),基于第二个见解,通过使用一个程序作为参考程序,并采用 DSE 来生成可以捕获参考程序行为的测试输入来计算。然后,我们在这些测试输入上运行另一个分析程序,并计算一致输入在生成输入中的比例作为SSE的值。由于测试生成仅基于参考程序,并且对分析程序不敏感,生成的测试输入可能无法测试分析程序中的某些行为。我们的第三个指标,配对程序符号执行(PSE),通过从两个程序构建一个配对程序来解决这个限制。配对程序的输入域与两个程序的输入域完全相同。配对程序在相同输入上运行两个程序,并断言它们的输出相同。然后,我们利用DSE在配对程序上生成测试输入,并计算通过断言的测试输入在生成输入中的比例作为PSE的值。由于 PSE 的测试生成是在从两个程序构建的配对程序上执行的,PSE也对分析程序敏感,并且可能比SSE揭示更多行为差异。

我们实现了一个工具来测量C#程序的这些三个行为相似性指标。我们实现了随机测试生成来计算 RS,并使用 Pex(一种最近作为 Visual Studio 2015 中的 IntelliTest 功能发布的最先进DSE引擎)来实现SSE 和PSE。我们在 Pex4Fun 平台上的三个真实世界课程中产生的学生代码工件上评估了我们的指标。评估结果显示,一般来说,RS 提供了对行为相似性的高度准确近似,但它可能无法区分小的行为差异。作为补充,PSE 在检测此类小的行为差异方面高度有效,但没有提供像 RS 那样好的近似。此类结果表明,这两个指标可以以互补的方式使用来提供更好的近似。我们还展示了我们指标的实际应用,包括提示生成、进度指示和自动评分。

我们的论文做出了以下主要贡献:

• 三种准确量化程序之间行为相似性的指标。这些指标可以相互补充,以进一步产生更好的结果。

• 一个基于Pex工具实现的开源工具。我们的工具可以从项目网站访问。

• 在Pex4Fun平台上的三个真实世界课程的代码工件上的评估,显示我们的指标RS和PSE在测量行为相似性方面高度有效。

• 展示了将我们的三个指标应用于编程和软件工程教育的演示。

本文的其余部分组织如下。第2节简要介绍了我们指标中使用的测试生成技术。第3节概述了测量行为相似性,包括一些定义和说明示例。第4节详细描述了我们的指标。第5节呈现了我们的评估结果。第6节展示了我们指标在编程和软件工程教育中的实际应用。第7节讨论了有效性的主要威胁。第8节讨论了相关工作,第9节总结了论文。

2. 背景

随机测试生成。 通常,随机测试生成将测试程序视为黑盒,并从程序的输入域中随机选择输入。随机测试生成的一种直接技术是根据均匀分布从输入域中随机采样值。还有其他高级采样输入策略,例如自适应随机测试和面向对象程序的基于反馈的技术 。由于随机测试生成技术不分析程序,其成本相对较低,使得随机测试生成高效。然而,随机技术的常见限制是它们往往无法为边界情况生成输入。对于我们的指标,我们使用一种简单的随机技术,从输入域中均匀采样输入。

基于DSE的测试生成。DSE探索程序的可行路径并生成测试输入来执行这些路径。DSE从任意或默认的具体输入开始,并沿着具体输入引导的路径符号执行程序。在路径执行过程中,DSE从分支中收集条件作为路径约束。然后DSE系统地否定路径约束的部分以形成新的路径约束,并利用约束求解器来求解这些路径约束以获得新的测试输入。这些新的测试输入引导未来的探索转向程序的不同路径。迭代地,DSE收集新的路径约束并生成新的测试输入以实现高结构覆盖率,例如语句覆盖率和分支覆盖率。随着约束求解器研究的进步,例如Z3 ,基于DSE的工具,如Pex 和SAGE ,在结构测试和安全/系统测试中显示了有前景的结果。

 3. 概述

为了量化两个程序的行为相似性,我们正式定义了行为相似性及相关概念,并使用示例说明这些定义。我们从正式定义程序执行开始。

定义1(程序执行)。程序P的执行是一个函数exec : ,将输入i ∈ I 映射到输出o ∈ O,其中I是P的输入域,O是P的输出域。

使用程序执行的定义,我们进一步定义程序之间的行为等价性和差异,以及测量两个程序在输入域上行为相似度的行为相似性。

定义2(行为等价性)。共享相同输入域I的两个程序P1和P2是行为等价的,表示为,当且仅当

图1显示了两个实现相同功能的程序,即行为等价的程序。这两个程序接受一个整数作为输入,如果数字在1000和9999之间,并且数字的所有位都相同,则返回字符串“fancy year”。第一个程序(图1a)通过显式边界检查和循环迭代每个位来实现此功能。第二个程序(图1b)枚举所有可能的fancy year并将输入与这些值进行检查。通过对两个程序的粗略检查可以确定,在所有可能的输入上,两个程序的输出总是一致。虽然两个程序在句法上看起来非常不同,但它们的行为是等价的。

定义3(行为差异)。共享相同输入域I的两个程序P1和P2是行为不同的,表示为,当且仅当

定义4(行为相似性)。共享相同输入域I的两个程序P1和P2之间的行为相似性是,其中, ,并且,

通常,I中的某些输入比其他输入更重要。例如,一些执行程序主要功能的输入并被更频繁使用的输入可能比其他输入更重要。为了处理此类场景,我们进一步将行为相似性扩展为加权行为相似性:P1和P2之间的加权行为相似性是,其中,  是的权重。

我们进一步定义一个偏序关系,即子集关系,相对于参考程序的两个程序。该关系可用于确定哪个程序更类似于参考程序。

定义5(行为包含)。 假设两个程序P1、P2和参考程序Pr都共享相同的输入域I,P2 在 Pr 的上下文中行为上包含 P1,表示为,当且仅当 ,,并且 ,

直观上,如果程序P2的行为包含程序P1的行为,当且仅当 P1 正确处理的输入集是 P2 正确处理的输入集的真子集。对于参考程序 Pr,如果程序 Pi 对某个输入正确处理,则当且仅当 Pi 和 Pr 在该输入上产生相同的输出。图 2 展示了一个说明行为相似性和包含关系的例子。参考程序显示在图 2a 中,而图 2b 和图 2c 中的程序是不完整的,因为它们仅对输入域的一个子集产生正确输出。这三个程序在满足条件 1 的输入上表现相同,但在不满足条件 1 的输入上表现不同。此外,程序 1 正确处理的所有输入也被程序 2 正确处理,但反之则不成立,因为程序 2 正确处理输入值 383 而程序 1 并没有。因此,程序 2 相对于参考程序比程序 1 更进一步。按照我们的定义,我们说程序2相对于参考程序行为包含程序1。换句话说,程序2相对于参考程序的行为相似性比程序1更高。

4. 行为相似性的指标

为了计算第3节中定义的两个程序之间的精确行为相似性,一种朴素的方法是在输入域中的每个输入上运行两个程序,比较两个程序的输出,然后计算一致输入的比例。此类方法对于具有无限输入的域是不切实际且不可行的。事实上,有许多程序,即使是非常简单的程序,其输入域也是无限的。例如,任何接受不受限制字符串作为输入的程序都具有无限输入域,因为字符串的长度可以任意长。对于这些程序,枚举每个输入简直不可能。即使输入域是有限的,在大多数情况下,由于输入域的巨大规模,按照定义计算行为相似性仍然不切实际。接受一个32比特的整数作为输入的程序具有大小为2^32的输入域。如果有其他参数,输入域的大小将是每个参数输入域大小的乘积,会很快膨胀。

为了解决这些问题,我们在计算行为相似性的精度和成本之间进行权衡。我们提出三种实际指标来计算两个程序之间的近似行为相似性。这些指标的目标是以低成本提供对实际行为相似性的高度准确近似。我们接下来详细描述这三种指标。对于每个指标,我们描述为什么提出此指标、如何计算它,以及此指标的优势和劣势。

 4.1 随机采样(RS)

由于通过枚举输入域中的所有可能输入来计算行为相似性是过于昂贵或不可行的,我们改为使用随机采样的输入来近似计算,从而降低成本。RS 背后的观点是,通过从输入域中均匀采样大量输入,基于采样输入计算的行为相似性可以准确近似实际的行为相似性。为计算 RS 的值,我们首先使用随机测试生成方法生成均匀分布在输入域上的输入。然后,我们分别在每个测试输入上运行两个程序以比较它们的输出。对于采样输入中一致的输入比例即为 RS 的值。RS 的正式定义如下:

定义6(RS)。Pr和Pc是共享相同输入域I的两个程序。Is是从I中随机采样的输入集,Ia是Is的子集,使得∀i ∈ Ia, 并且 , 。RS指标定义为

RS是一种直接但有效且高效(即低成本)的指标,用于近似行为相似性。当输入域巨大,甚至无限时,RS总是可以采样负担得起的输入部分来计算对实际行为相似性的合理良好近似。由于RS将程序视为黑盒,并且不分析程序进行测试生成,生成测试输入和测量RS的成本相当低甚至可以忽略。另一方面,由于黑盒测试生成,它可能错过一些揭示程序之间小行为差异的输入(例如边界情况),从而无法区分略有不同的程序。

 4.2 单程序符号执行(SSE)

单程序符号执行(SSE)指标基于一个观点来估算行为相似性,即程序路径的数量通常远小于输入域的大小。程序路径可以视为程序行为的更简洁表示。如果我们为程序中的每个路径选择一个输入,那么这些输入将探索程序的代表性行为。因此,通过仅在参考程序的代表性输入上运行待分析程序并比较它们的输出来测量行为相似性就成本较低。由于最近的DSE进展,我们利用DSE技术有效地探索程序路径。为了计算SSE,我们选择一个程序作为参考程序,并应用DSE生成捕捉参考程序行为的测试输入。然后,我们在这些测试输入上运行另一个程序,并计算生成输入中一致输入的比例作为SSE的值。SSE的正式定义如下:

定义7(SSE)。Pr和Pc是共享相同输入域I的两个程序,Pr是参考程序。Is是由DSE在Pr上生成的输入集,Ia是Is的子集,使得∀i ∈ Ia, 并且 , 。SSE指标定义为

与RS相比,SSE探索不同的可行路径来生成测试输入。因此,这些测试输入更有可能覆盖程序的边界情况。揭示此类边界情况有助于区分具有小行为差异的程序。但SSE仍有局限性。首先,SSE从未考虑分析程序,而是仅基于参考程序生成测试输入。生成的测试输入不一定捕捉到被分析程序的所有行为。所有生成的测试输入可能在两个程序上都一致,但被分析的程序仍然可能有一些额外的行为(未被测试输入揭示),这些行为与参考程序的行为不同。在这种情况下,SSE会错误地将这两个程序视为行为等价的。其次,当程序中有循环,其迭代计数取决于无界输入时,程序可能具有无限多的路径。对于这些程序,枚举所有程序路径也是不可行的。为了解决这个问题,我们可以绑定输入域或循环迭代计数来枚举程序路径的子集作为近似。

4.3 配对程序符号执行(PSE)

为了解决SSE可能无法揭示分析程序中的行为这一限制,我们的配对程序符号执行(PSE)通过从参考程序和被分析程序构建一个配对程序来计算,并通过探索配对程序中的路径来生成测试输入。图3展示了构建配对程序的模板。配对程序与这两个程序共享相同的输入域,并且向两个程序提供相同的输入,同时断言两个程序的输出相同。在基于配对程序生成测试输入时,DSE尝试分别生成通过和未通过断言的测试输入。通过断言的输入表明这两个程序在这些输入下产生相同的输出,而未通过断言的输入表明这两个程序产生不同的输出。因此,我们计算通过断言的测试输入的比例作为PSE的值。PSE的定义如下:

定义8(PSE)。 给定共享相同输入域I的两个程序Pr和Pc,我们构建配对程序的形式为,其中assert是一个接受条件作为输入并断言条件为真的函数。让表示输入i在上的执行通过断言。让Is是由DSE在上生成的输入集,Ia是Is的子集,使得∀i ∈ Ia,  并且, 。PSE指标定义为

由于PSE的测试生成是基于从两个程序构造的配对程序,因此PSE通过避免生成的测试输入捕捉参考程序的行为而非被分析程序的行为,改进了SSE。然而,PSE仍然面临在某些配对程序中处理无限路径的相同挑战。为了缓解这个问题,我们可以再次限制输入域或循环迭代次数。此外,PSE在配对程序中要探索的路径是两个程序路径的组合。因此,PSE在路径探索上的成本高于SSE。

5. 评估

我们在Pex4Fun平台 的三个真实世界数据集上评估了我们提出的指标的有效性。我们的评估旨在回答以下两个研究问题:

RQ1:我们的指标在根据程序向参考程序的进度来对程序排序方面的有效性如何?

RQ2:我们的指标在近似行为相似性方面的准确性如何?

RQ1的答案显示了我们的指标在确定程序之间行为等价性和包含关系方面的有效性。RQ2的答案显示了我们的指标在量化程序之间行为相似性方面的准确性。

5.1 评估对象和设置

对象。Pex4Fun允许教师提出一组编程任务,每个任务与一个秘密解决方案程序相关联。学生不断提交他们的程序,直到提交的程序与解决方案程序的行为相同。我们从Pex4Fun平台的三个真实课程中构建三个数据集,即CSharp4Fun、APCS和ICSE2011。CSharp4Fun是一个介绍C#基础的短课程,其中有一组练习基本编程概念的任务。APCS是一个伴随课程,包含针对高级计算机科学学生的系列练习。ICSE2011是ICSE 2011上举办的Pex4Fun竞赛中使用的一组编程任务。这些课程包含各种编程任务,从算法问题和面向对象设计问题到测试问题。对于课程中的每个任务,我们收集参考程序和学生提交的程序序列。通常,这些任务的提交程序和参考程序的大小从几行到一百行代码。我们然后过滤掉那些具有句法错误的提交,因为我们的评估关注程序的行为。请注意,我们数据集中的一个序列对应于一个学生针对一个任务的提交序列。表1显示了我们的对象的详细信息,包括任务数量、学生数量和学生提交的程序数量。

评估设置。为了回答RQ1,我们从我们的数据集中随机采样程序序列,每个序列满足以下属性之一:(1) 序列有一个后续程序与先前程序行为等价;(2) 序列有一个后续程序相对于参考程序行为包含先前程序。换句话说,序列是有序的,先前程序要么与后续程序行为等价,要么被后续程序包含。由于选择过程需要大量手工努力,我们选择了60个此类序列(每个数据集20个)用于我们的评估。

为了测量每个指标在基于程序向参考程序的进度对程序排序方面的有效性,我们为每个序列中的每个程序计算所有三个指标值,并验证一个指标的计算值是否符合序列顺序。换句话说,两个等价程序应该具有相同的值,包含另一个的程序应该具有比另一个更高的值。如果指标的计算值符合序列的顺序,则将指标标记为正确指示序列中程序的进度。我们使用指标产生正确顺序的序列百分比来显示指标在指示程序进度方面的有效性。指标的百分比越高,说明该指标在指示程序排序方面越准确。

为了回答RQ2,我们选择手动计算两个程序之间行为相似性可行的任务,然后检查我们的指标值如何准确近似手动计算的行为相似性。对于RQ2,我们也从这些任务中随机采样60个序列(每个数据集20个)。对于序列中的每个程序,我们手动计算程序与参考程序之间的行为相似性。为了确保手动计算的行为相似性的可靠性,我们至少有两个作者同意每个手动计算的结果。如果程序的输入域是无限的,我们为输入域提供界限。我们将整数绑定在区间[-2147483648, 2147483647]内(即32位整数)。我们将字符串的长度绑定为10,字符串中的每个字符仅来自ASCII表(即8位字符)。我们还将数组的长度绑定为10。此外,我们排除任何接受浮点数作为输入的任务,因为即使有界限,我们也无法枚举浮点数。我们计划在未来工作中设计其他方法来评估我们指标在接受浮点数作为输入的程序上的表现。

有了有界的有限输入域,对于序列Qj中的任何程序Pi,我们手动计算Pi与其参考程序之间的实际行为相似性Sij,以及使用我们的工具在这些两个程序上的每个指标Mij的值。我们通过手动计算的行为相似性和指标值之间的绝对误差来测量每个指标的准确性,如下所示:

我们进一步计算每个主题数据集中的所有程序的平均绝对误差及其标准差,以显示我们的指标在近似行为相似性方面的整体有效性。

5.2 RQ1:指示进度的有效性

表2显示了我们对RQ1的评估结果摘要。列“Subject”显示数据集主题。列“#Seq.”显示从每个数据集中选择的程序序列数量。列“#Tasks”显示选定序列中包含的不同任务数量。列“#Avg. Length”显示每个序列中包含的程序平均数量。列“#CO of RS”、“#CO of SSE”和“#CO of PSE”显示RS、SSE和PSE产生基于行为相似性的正确顺序的序列数量。

如表所示,PSE在对序列排序方面表现最佳。在60个序列中的52个(87%)上,它成功产生了正确顺序。其良好表现的原因是它在配对程序上进行路径探索,结合了参考程序和提交程序。因此,PSE对提交程序的变化敏感。通常,提交程序中有两种变化可以被PSE有效检测:(1) 导致配对程序中不同或附加路径的控制流变化;(2) 使配对程序中先前不可行路径变得可行的非控制流变化。PSE可以检测这些变化,因为对这两个配对程序(变化前后)的路径探索识别了两个不同的路径集。基于路径探索计算的指标值也因此不同。如果分析程序中的此类变化能够正确处理更多输入,PSE通常可以生成更多通过的测试输入,从而增加指标值。以这种方式,PSE有效指示程序之间的进度。其他两个指标RS和SSE在对序列产生正确顺序方面表现不佳,因为它们对提交程序的变化不敏感(不基于提交程序生成测试输入)。换句话说,给定参考程序,它们都在固定测试输入集上运行任何提交程序。因此,它们往往无法区分两个具有轻微行为差异的提交程序。

图4显示了我们数据集中一个简单的示例,其中PSE成功指示程序之间的进度。图4a、4b、4c和4d分别显示参考程序、两个提交的不正确程序(提交1和2),以及PSE构建的配对程序模板。可以观察到1精确正确处理一个输入(0),2精确正确处理两个输入(0和42)。根据行为包含的定义,1相对于参考程序被2行为包含(即2在1的基础上取得了进展)。虽然这两个提交程序之间的行为差异非常小(仅在一个输入上),PSE仍然可以正确指示进度,因为从1到2有控制流变化。PSE通过用1和2替换模板中的Submission方法来构建两个配对程序。PSE然后探索中的路径,并发现中有两个可行路径,其中一个导致断言违反。类似地,PSE发现中的三个可行路径中有一个导致断言违反。因此,1和2的指标值是0.5 = 1/2和0.67 = 2/3,这正确反映了1和2之间的顺序。然而,RS和SSE都在图4的示例上失败。为了区分1和2,它们需要生成测试输入x = 42。RS生成42作为x的概率是1/2^32,接近0。对于SSE,由于它仅基于参考程序生成测试输入,在这种情况下它仅生成一个输入x = 0(整数的默认值),因为参考程序中只有一个路径。

总共有8个序列上PSE产生错误顺序,对应8个失败。我们调查了这些错误顺序并识别了两个主要原因。对于8个失败中的3个,PSE未能检测行为差异,因为变化没有修改配对程序的控制流。考虑一个极端示例,其中参考程序接受整数x作为输入并总是返回1,无论输入如何。假设先前提交P1简单返回x,后续提交P2返回x^2。很容易看出两个程序都不等价于参考程序,但P2包含P1,因为P2除了输入1外还正确处理输入-1。然而,当计算PSE的指标值时,P1和P2的配对程序都有两个路径,其中一个路径违反断言。因此,PSE为每个配对程序生成两个执行两个路径的测试输入,并为P1和P2给出相同的指标值0.5。本质上,由于配对程序的控制流和每个路径的可行性保持不变,生成的通过测试输入的百分比保持不变。另一个主要原因(8个失败中的4个)是配对程序中的控制流变化实际上降低了通过测试输入的百分比。通常,变化允许当前程序正确处理附加输入,指标值应该增加。然而,在一些边界情况下,控制流变化影响Pex的路径探索并降低通过测试输入的百分比。例如,虽然Pex生成更多通过测试输入,但它可能生成更多失败测试输入,从而使指标值降低。

5.3 RQ2:量化行为相似性的有效性

表3显示了我们对RQ2的评估结果摘要。列“Subject”显示数据集主题。列“#Seq.”显示从每个数据集中选择的提交序列数量。列“#Tasks”显示选定序列中包含的不同任务数量。列“#Avg. Length”显示每个序列中包含的程序平均数量。列“AE/SD of RS”、“AE/SD of SSE”和“AE/SD of PSE”分别表示RS、SSE和PSE的平均绝对误差及其标准差。

如表3所示,RS比其他两个指标更好地近似实际行为相似性。其整体平均绝对误差(0.017)和标准差(0.044)非常接近0。其准确近似的原因是RS确保随机生成的输入均匀分布在输入域中。考虑输入域I作为两个大分区,一个分区Ia包含所有一致输入,另一个分区Id包含所有不一致输入。行为相似性计算为|Ia|/|I|。由于RS均匀采样输入,采样一致输入的可能性也是|Ia|/|I|。因此,当RS采样显著数量的输入时,采样一致输入的百分比(RS的指标值)将非常接近|Ia|/|I|。

SSE和PSE没有很好地近似行为相似性,因为它们仅基于路径探索计算指标值。它们通过简单路径计数隐式地为每个路径赋予相等的权重。然而,每个路径对应的输入分区可能在大小上不同。为了提供更准确的近似,我们需要基于其对应输入分区的大小为每个路径分配权重。在未来工作中,我们计划调查执行路径的概率如何用于改进SSE和PSE。

有趣的是,在某些情况下,SSE和PSE提供了极度准确的近似(例如,对行为相似性产生完美值)。在这种情况下,程序的输入域通常非常小(DSE引擎在其时间界限内可以枚举),并且每个输入导致程序中的唯一路径。当DSE穷尽探索程序中的所有路径时,它实际上枚举了输入域中的所有输入。生成的测试输入是所有可能输入的集合。因此,为SSE和PSE计算的指标值正是实际行为相似性。图5显示了我们数据集中这样一个示例,其中SSE和PSE都为行为相似性产生了完美指标值。图5a中的程序是参考程序,图5b和5c中的程序是一个不正确提交和一个正确提交。可以看出参考程序的每个输入都导致唯一路径。由于byte参数的值范围是从0到255,参考程序中总共有256个路径。当基于参考程序生成测试输入时,SSE可以轻松探索所有路径并生成256个测试输入,由0到255的每个byte值组成。类似地,提交1和2的配对程序也有256个路径。PSE穷尽探索所有256个路径并生成与SSE相同的测试组。由于SSE和PSE生成的测试输入都是所有可能输入的集合,计算的指标值正是实际行为相似性。

计算三个指标的成本是可以接受的。正如预期,RS的成本比其他两个指标低。计算RS的主要成本是在两个程序上运行采样输入。由于我们关注入门程序,在这些程序上运行一个输入的时间范围从毫秒到一秒。计算一对程序的RS成本通常少于一分钟(在许多情况下,仅几秒)。我们可以通过控制样本集的大小进一步降低RS的成本。对于SSE和PSE,主要成本是输入生成。生成输入的成本包括分析成本(例如,符号执行、约束求解)和执行成本(例如,具体执行)。由于DSE实际执行具体执行,我们不仅获得输入,还获得输入生成后的输出。因此,我们不需要再次运行生成的输入来获得输出。我们为程序的输入生成设置了两分钟的时间界限。因此,计算SSE和PSE的成本最多略超过两分钟。通常,计算一对程序的SSE和PSE的成本范围从十秒到一分钟。

 6. 行为相似性的应用

我们的行为相似性指标有广泛的应用,用于改善在线编程和软件工程教育。我们接下来详细讨论三个实际应用。

进度指示。 我们的指标可以用作学生编码过程中的进度指示器。我们可以在学生编码时在后台不断计算指标值,并实时显示指标值作为进度指示器。请注意,我们不为具有句法错误的代码计算指标值,因为此类代码无法运行。我们相信此类指示器对学生有用,以便他们能够跟踪他们的进度。通常,如果他们观察到增加的指标值,他们知道他们正在沿着正确的方向前进。因此,他们可能对他们的编码更有信心。如果他们观察到显著下降,很可能他们正在做错事。他们可能及早停止并避免进一步错误。

正如我们的评估所示,PSE在区分小行为差异方面最有效,而RS在近似实际行为相似性方面非常有效。我们可以结合这两个指标来产生更有信息的进度指示器。具体而言,我们可以使用PSE来指示是否有任何进度,并使用RS来指示进度有多大。考虑图2中的示例。虽然程序2在程序1上取得了进度,但进度很小,并且程序2实际上朝着参考程序的错误方向前进(过度拟合某些特定输入)。如果我们为两个程序计算相对于参考程序的PSE,结果值为程序1的0.67和程序2的0.80,表明程序2在程序1上取得了实质进度。类似地,如果我们也计算RS的指标值,结果值为两个程序的0.13相同,表明程序2没有在程序1上取得任何进度。因此,PSE或RS单独都无法提供实际进度的准确信息。然而,如果我们如建议结合这两个指标,我们可以得出正确结论,即虽然程序2在程序1上取得了进度(程序2具有更高的PSE指标值),但进度并不实质(程序1和2具有相同的RS指标值)。

自动评分。为了减少教师的评分负担,我们可以使用我们的指标来改进句法方法的自动评分。学生程序与参考程序之间的行为相似性可以是评分的一个因素。更高的相似性通常表明更高的分数。由于我们的指标纯粹基于程序语义,我们可以将我们的指标与其他句法方法结合来产生更好的自动评分器。句法方法处理我们的指标在学生程序与参考程序句法上非常相似但语义上相当不同的情况下的局限性(例如,在大输入域上缺少健全性检查)。我们的指标处理句法方法在学生程序语义上与参考程序非常相似但句法上相当不同的情况下的局限性(例如,图1中的程序)。整合句法和语义方法来产生最终分数的各种方式。例如,我们可以使用加权行为和句法相似性的和作为最终分数。或者,我们也可以使用行为和句法相似性的最大值作为最终分数。

此外,我们的指标还提供了为输入添加权重的灵活性。通常,在实践中,并非每个输入都具有相同的重要性。一些执行任务主要功能的输入可能携带更高的权重,而一些由健全性检查过滤的其他输入可能携带较低的权重。我们加权的行为相似性允许教师轻松指定输入域上的权重。

提示生成。我们还可以使用我们的指标在学生编码过程中为学生生成提示。由于学生无法总是从他人那里获得及时帮助,当他们遇到问题时基于他们的当前代码自动生成提示是有益的。这个想法,受众包启发,是利用我们的指标从其他学生那里找到行为相似的程序作为提示。具体而言,假设学生Si在他们的当前程序Pi上需要帮助。我们可以首先使用RS计算Pi与参考程序Pr之间的行为相似性。然后我们在其他学生的提交中搜索,并找到一个提交(来自已成功完成任务的学生),其相对于Pr的相似性等于或最接近。k表示提交序列的第k个()提交。接下来,我们进一步查看学生的提交序列,并选择作为提示程序的第一个提交,使得k < n 并且。直观地说,提示程序包含了对程序的即时进度。由于Pi类似于,通过查看,学生可能得到向解决方案下一步的提示。我们甚至可以使用DSE生成一些提示输入,这些输入在Pi和上产生不同的输出,以便学生知道下一步要处理哪些输入。请注意,将此技术与句法分析结合是可取的。当搜索时,找到句法相似的程序也很重要。如果在句法上与Pi非常不同,学生可能需要花费更多时间理解提示程序。更重要的是,下一步可能不适用于Pi。

 7. 有效性威胁

外部有效性的威胁主要在于我们评估中使用的数据集的通用性。所有三个数据集都从Pex4Fun平台收集,并且所有程序仅用C#编写。虽然此类数据集对于Pex4Fun平台和面向对象语言具有代表性,但它们可能不代表其他平台(例如MOOC)和编程语言(例如脚本和函数式语言)。在未来工作中,我们计划在各种平台的数据集上评估我们的指标,并为其他类型的编程语言开发行为相似性指标。

内部有效性的威胁主要是我们评估中的潜在人为错误。对于回答RQ1的子集关系确定需要大量手动努力。此外,用于RQ2评估的行为相似性的手动计算可能复杂且易出错。这些威胁通过双重检查所有手动工作来缓解。结果由至少两个作者单独验证和交叉检查。我们软件评估框架中可能也存在一些故障,这些故障可能影响我们结果的有效性。此威胁通过在进行评估前广泛测试系统来缓解。

 8. 相关工作

自动评分。Alur et al.  提出了一种方法,将学生的不正确确定性有限自动机(DFA)与参考DFA进行比较。他们的方法使用捕获基于句法编辑距离的句法差异和基于接受字符串输入的语义差异的技术来分配部分分数。虽然他们的方法和我们的方法使用类似的语义相似性概念,但他们的方法适用于DFA,而我们的指标适用于程序。

Singh et al. 提出了一种方法,自动确定使学生不正确解决方案匹配参考解决方案行为的最小修复。他们的方法关注通过计算到参考解决方案的最小句法距离来提供如何修复不正确解决方案的反馈,而我们的指标关注量化两个程序的语义相似性。我们指标可以识别具有不同句法结构的相似程序。

还有以前的工作利用学生程序与参考程序的语义相似性 。此类方法执行语义保持转换来标准化学生程序和参考程序,并比较它们的系统依赖图来计算相似性。我们不是比较系统依赖图,而是比较程序的输入/输出对来计算行为相似性,从而可以识别具有不同系统依赖图的相似程序。

等价性检查。有几种方法使用程序依赖图 、输入-输出依赖 、符号摘要和副作用摘要来检查程序的语义/行为等价性。所有这些方法对等价性检查产生布尔答案,其中一些还产生行为差异。然而,除了等价性检查外,我们的方法还量化两个程序的相似程度。据我们所知,我们是第一个提出量化程序行为相似性方法的人。

Jiang et al. 提出了一种通过随机测试识别功能等价代码片段的方法。他们的方法基于输入/输出行为而不是句法结构考虑两个代码片段等价。我们RS指标在利用随机测试方面类似于他们的方法。然而,我们提出两个附加指标,使用基于DSE的测试生成,并在检测代码片段之间小变化方面优于RS指标。

基于测试用例的反馈。Hext et al. 提出了一种方法,通过将存储的数据与通过执行不正确程序生成的数据进行比较来自动评分简单程序练习。Jackson et al. 提出了一种方法,自动检查程序和编程风格的正确性,如模块性、复杂性和效率。Pex4Fun使用DSE生成导致不正确程序和正确程序产生不同输出的测试输入。所有这些方法通过显示失败测试用例的测试输入来产生反馈,而我们的指标测量在学生程序和参考程序上产生相同输出的输入比例,并可用于进度指示和提示生成。

代码克隆检测。 研究人员提出了计算代码片段各种表示的相似性来自动识别代码克隆的方法,例如标记化语句 、抽象语法树 、程序依赖图和基于句法单元(例如类和函数)的指标。这些克隆检测方法关注源代码片段,并基于代码片段的句法或语义表示计算相似性。与这些通过静态分析代码工件来计算相似性的静态方法不同,我们是一种动态方法,通过运行程序产生输入/输出对来计算相似性。

9. 结论

在本文中,我们提出了三种指标,即RS、SSE和PSE,来近似程序之间的行为相似性。我们利用测试生成技术来生成输入,并通过在程序上运行输入来计算指标值。我们基于Pex实现了我们的指标,并在Pex4Fun平台的三个数据集上评估了它们。评估结果显示,RS提供了对行为相似性的最佳近似,平均绝对误差为0.017,但可能无法指示程序的小进度。作为补充,PSE在基于行为相似性对程序排序方面有效(87%情况下正确),但没有提供像RS那样好的近似。在未来工作中,我们计划将这两个指标整合成一个既提供良好近似又敏感的指标。我们还展示了我们的指标在在线编程和软件工程教育中的多项应用,包括进度指示、自动评分和提示生成。

启发

文章提出了RS、SSE和PSE三种指标,展示了如何利用动态符号执行(DSE)和随机测试技术解决在线教育中行为相似性量化的难题,体现了数据驱动的实验设计和工具开发的实践价值;作者在Pex4Fun平台上的真实数据评估揭示了RS在近似相似性上的优势及PSE在检测细微差异上的潜力,我们在研究中也可以探索多方法互补;文章将成果应用于进度指示、自动评分和提示生成,我们在研究中也应关注实际应用场景;

BibTeX

@inproceedings{li2016measuring,
  title={Measuring code behavioral similarity for programming and software engineering education},
  author={Li, Sihan and Xiao, Xusheng and Bassett, Blake and Xie, Tao and Tillmann, Nikolai},
  booktitle={Proceedings of the 38th International Conference on Software Engineering Companion},
  pages={501--510},
  year={2016}
}
### 数据集和度量标准 对于评估开放性语言生成中的偏见,多个数据集和度量已经被开发出来以确保模型输出的公平性和无偏性。具体来说: #### 常用的数据集 为了检测不同类型的偏差,研究人员创建了专门针对这一目的设计的数据集。例如,Winogender Corpus 是一种广泛使用的资源,它包含了性别刻板印象的例子[^1]。另一个例子是 StereoSet,该数据集中含有涉及职业、外貌等多个维度的社会群体描述,旨在测试模型是否会强化负面或不准确的社会成见。 #### 度量标准 衡量偏见的程度通常依赖于一系列定量分析工具和技术。其中一些方法包括但不限于: - **Demographic Parity (DP)**:此度量关注的是特定属性组之间的分布差异,比如性别或种族,在给定条件下产生的概率应该相等。 - **Equal Opportunity Difference (EOD)**:这种度量侧重于正类别的条件独立性,即如果两个个体属于不同的受保护类别但在其他方面相同,则他们获得有利结果的机会应该是相同的。 - **Disparate Impact (DI)**:这是一种统计学上的概念,用来识别是否存在不成比例的影响,特别是在就业等领域中可能存在的间接歧视现象。 除了上述传统机器学习领域内的评价指标之外,还有一些专门为自然语言处理定制的新颖方案被提出。例如,通过计算某些敏感词出现频率的变化来量化潜在的文化倾向;或者利用对抗验证框架自动发现并修正隐藏模式下的不公平待遇。 ```python def calculate_demographic_parity(predictions, protected_attribute): """ 计算人口统计学平等. 参数: predictions (list): 模型预测的结果列表. protected_attribute (list): 受保护特征对应的标签列表. 返回: float: DP值. """ from collections import Counter pred_by_group = {} for pred, attr in zip(predictions, protected_attribute): if attr not in pred_by_group: pred_by_group[attr] = [] pred_by_group[attr].append(pred) group_counts = {k: sum(v)/len(v) for k, v in pred_by_group.items()} max_count = max(group_counts.values()) min_count = min(group_counts.values()) return abs(max_count - min_count) # 使用样例 predictions = ['positive', 'negative', ... ] # 替换为实际预测结果 protected_attributes = ['male', 'female', ... ] # 替换为对应的人口统计数据 dp_value = calculate_demographic_parity(predictions, protected_attributes) print(f'Demographic parity value is {dp_value:.4f}') ```
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值