一种基于强化学习的程序验证方法及装置与流程

文档序号:24305858发布日期:2021-03-17 00:58阅读:214来源:国知局
本发明涉及程序验证
技术领域
:,具体而言,涉及一种基于强化学习的程序验证方法及装置。
背景技术
::程序是复杂的,容易出错的,人工测试无法保证测试的完备性,因此程序验证是必要的,特别是对程序安全有极高敏感度的领域,如航空航天领域等。cegar(counter-exampleguidedabstractrefinement,反例制导的抽象精化)是程序验证中一种重要的方法,在对程序进行抽象建模的基础上,该技术基于从当前抽象层次中抽取不可达的错误路径,也可以称为反例路径,来迭代地精化抽象模型,将模型从最初抽象层次很高的状态精化为接近真实程序行为的状态。在cegar的框架中,当找到一条反例路径时,可以使用不同的抽象域进行反例消除。但是不同的抽象域在进行反例消除时,所花费的代价和能从反例路径中抽取出的信息往往是不同的,即他们会影响程序验证的效率。因此,如何在cegar的框架下,有效地进行抽象域的选择成为影响程序验证效率的重要因素。传统的方法需要专家经验在程序中获取有限的特征,再通过大量实验对特征进行排序得到一个通用的启发式决策,以基于该启发式决策确定抽象域。然而,这种方法需要耗费大量的时间成本,抽象域的确定过程效率较低。技术实现要素:本发明提供了一种基于强化学习的程序验证方法及装置,以提高抽象域确定的效率。具体的技术方案如下。第一方面,本发明实施例提供一种基于强化学习的程序验证方法,所述方法包括:获取待验证程序;所述待验证程序包括多个子程序,各所述子程序具有先后执行顺序关系;运行所述多个子程序中的第一个子程序,在所述第一个子程序运行过程中统计得到所述第一个子程序对应的第一程序特征;将所述第一子程序的下一子程序作为当前子程序,将所述第一程序特征作为当前程序特征;将所述当前程序特征输入预先训练得到的神经网络模型中,得到所述当前程序特征对应的当前抽象域;所述神经网络模型为预先根据各样本子程序,以及各所述样本子程序对应的样本抽象域训练得到的;基于所述当前抽象域,对所述当前子程序进行验证,并在验证过程中统计得到所述当前子程序对应的当前程序特征;判断是否存在未验证的子程序;当存在未验证的子程序时,将所述当前子程序的下一子程序作为当前子程序,返回执行所述将所述当前程序特征输入预先训练得到的神经网络模型中,得到所述当前程序特征对应的当前抽象域的步骤。第二方面,本发明实施例提供一种基于强化学习的程序验证装置,所述装置包括:程序获取模块,用于获取待验证程序;所述待验证程序包括多个子程序,各所述子程序具有先后执行顺序关系;特征提取模块,用于运行所述多个子程序中的第一个子程序,在所述第一个子程序运行过程中统计得到所述第一个子程序对应的第一程序特征;程序处理模块,用于将所述第一子程序的下一子程序作为当前子程序,将所述第一程序特征作为当前程序特征;抽象域确定模块,用于将所述当前程序特征输入预先训练得到的神经网络模型中,得到所述当前程序特征对应的当前抽象域;所述神经网络模型为预先根据各样本子程序,以及各所述样本子程序对应的样本抽象域训练得到的;程序验证模块,用于基于所述当前抽象域,对所述当前子程序进行验证,并在验证过程中统计得到所述当前子程序对应的当前程序特征;程序判断模块,用于判断是否存在未验证的子程序;当存在未验证的子程序时,将所述当前子程序的下一子程序作为当前子程序,触发所述抽象域确定模块。由上述内容可知,本发明实施例提供的基于强化学习的程序验证方法及装置,能够基于强化学习的方法,在获取到各子程序的程序特征后,通过预先训练得到的神经网络模型确定各抽象域,神经网络模型具有计算速度快的特点,因此,可以提高抽象域确定的效率。当然,实施本发明的任一产品或方法并不一定需要同时达到以上所述的所有优点。本发明实施例的创新点包括:1、基于强化学习的方法,在获取到各子程序的程序特征后,通过预先训练得到的神经网络模型确定各抽象域,神经网络模型具有计算速度快的特点,因此,可以提高抽象域确定的效率。2、预先通过各样本子程序,以及各样本子程序对应的样本抽象域,基于强化学习的方法训练得到神经网络模型,可以提高神经网络模型的训练速度和准确性。3、在获取到样本程序特征之后,通过对非布尔类型的目标样本程序特征进行升维处理,能够在神经网络模型的训练过程中,降低神经网络模型的误差降低速率,进而提高抽象域确定的准确性。附图说明为了更清楚地说明本发明实施例或现有技术中的技术方案,下面将对实施例或现有技术描述中所需要使用的附图作简单介绍。显而易见地,下面描述中的附图仅仅是本发明的一些实施例。对于本领域普通技术人员来讲,在不付出创造性劳动的前提下,还可以根据这些附图获得其他的附图。图1为本发明实施例提供的基于强化学习的程序验证方法的一种流程示意图;图2为本发明实施例的特征抽取框架示意图;图3为本发明实施例的原始激励设计示意图;图4为本发明实施例的强化学习的训练流程示意图;图5为本发明实施例的强化学习的测试过程示意图;图6为本发明实施例的基于强化学习的程序验证装置的一种结构示意图。具体实施方式下面将结合本发明实施例中的附图,对本发明实施例中的技术方案进行清楚、完整的描述。显然,所描述的实施例仅仅是本发明的一部分实施例,而不是全部的实施例。基于本发明中的实施例,本领域普通技术人员在没有付出创造性劳动前提下所获得的所有其他实施例,都属于本发明保护的范围。需要说明的是,本发明实施例及附图中的术语“包括”和“具有”以及它们的任何变形,意图在于覆盖不排他的包含。例如包含的一系列步骤或单元的过程、方法、系统、产品或设备没有限定于已列出的步骤或单元,而是可选地还包括没有列出的步骤或单元,或可选地还包括对于这些过程、方法、产品或设备固有的其他步骤或单元。传统的基于复合cpa(configureableprogramanalysis,可配置程序分析)的程序验证,会根据cpa算法计算程序的动态抽象可达图,再通过迭代地进行反例寻找和反例消去的方式来调整相应cpa算法中抽象域的精度。即通过多次cegar来寻找到合适的抽象,来验证程序。但是传统方法在复合抽象域中,每次会优先用简单的抽象域来消去反例,若不能消去,再用更加复杂的抽象域分析尝试反例消去,这样的缺点是,如果当前反例只能通过复杂的抽象域消去,则会多进行一次不成功的反例消去,带来时间的损耗。与此同时,如果错误路径中有循环变量,则可能就算当前用简单分析消去了反例,之后还会因为循环展开有类似的反例出现,从而导致cegar的轮数会变多。改进的算法是通过计算错误路径的变量域值分数,判断是否超过阈值,如果没有超过,就优先用简单的显式值分析,否则,就优先用谓词分析。但是,这个方法也有问题,这种经验式的方法就是针对某一类型的程序比较有用,对于其他程序来说,还应该考虑更加复杂的因素,比如当前程序本身的函数个数和循环个数,以及验证过程中我们已经做了几次cegar。要想得到一个比较好的策略,重点就是要准备多样的实验数据,也就是待验证的程序,以及对验证中的程序进行特征抽取。我们想要通过强化学习,来学得对抽象域选择的策略,那么就需要一种方式来表达被验证程序当前的状态,也就是在cpachecker对程序的验证过程中的一种状态表示。而状态可以用一些属性或者特征的向量来表示,那抽取这个状态向量过程就被称为程序特征抽取。图1为本发明实施例提供的基于强化学习的程序验证方法的一种流程示意图。该方法应用于电子设备。该方法具体包括以下步骤。s110:获取待验证程序;待验证程序包括多个子程序,各子程序具有先后执行顺序关系。s120:运行多个子程序中的第一个子程序,在第一个子程序运行过程中统计得到第一个子程序对应的第一程序特征。在一种实现方式中,本发明实施例的程序特征可以由两大类组成,静态特征和动态特征,静态特征指整个验证过程都不会变化的特征,而动态特征则相反。对于待验证程序,我们定义程序本身固有的属性为静态特征,主要有变量个数,函数个数,循环个数等组成。在cpachecker的验证开始后,也会通过对程序的静态分析构造出控制流图,而这个控制流图在整个验证过程中也不会变动,因此控制流图的一些属性,比如节点个数,也属于静态特征。另外,在静态特征的抽取过程中,引入了与可达性分析相关的变量的概念,在这里进行说明。变量的可达性决定于变量在cfa的assumption边中的使用方式是否是右值。而可达性也可以通过数据流中的依赖关系进行传递,最后计算出的传递闭包就是所有与可达性分析相关的变量。本发明实施例中,静态特征一共包括24个。具体的,可以包括程序结构特征、程序变量特征、以及程序语义特征。代码级别静态特征,根据特征类型分,有布尔型特征和整数型特征。布尔型特征主要体现了程序本身的语法特性,强调不同数据结构的存在性。如果一个程序没有循环,且都是布尔型变量,那么程序用简单的值分析就能得到很快的解决。因此,不同特征之间也可能有关联,从而共同决定之后的决策。整数型特征则在语法上更强调量级。如果循环的个数越多,则越可能采用复杂一点的谓词分析;如果布尔变量越多,则越可能采用值分析。但根据来源分,可以分为程序结构特征,程序变量特征,程序语义特征。程序结构特征体现了程序控制流图上的一些信息,如是否有循环和递归调用等。而有循环的程序普遍来说会比较复杂,也更可能采用复杂的抽象域快速得到验证结果。具体的,程序结构特征有:1.program_requires_loop_handling:程序中是否出现了循环且需要处理。在cpachecker中,会对程序进行预处理分析,包括检查死代码等,如果循环出现在了可达性分析的控制流图上,则为true,否则为false。2.program_containing_external_functions:程序中是否有出现外部函数。3.number_of_functiions:所有函数的个数。4.number_of_loops:程序中循环的个数。5.number_of_intbool_partitions:程序的函数中只有布尔变量的函数的个数。6.number_of_int_add_partitions:程序的函数中只有用作加法的变量的函数的个数。7.number_of_nodes:程序所对应的cfa节点的个数,和配置相关,精确配置则体现了程序语句的个数。如果使用块编码原则,程序结点的个数将小于语句的个数。程序变量特征体现了程序中的变量信息,包括不同类型的变量个数。程序所包含的变量类型越复杂,也能体现程序越复杂。程序变量特征有:1.program_contain_only_relevant_bools:程序中与可达性相关的变量是否只有布尔类型的变量。2.program_requires_composite_type_handling:程序中与可达性相关的变量中是否出现了结构体等复杂数据。3.program_requires_array_handling:程序中与可达性相关的变量中是否出现了数组。4.program_requires_float_handling:程序中与可达性相关的变量中是否出现了浮点数。5.relevant_bool_vars_ratio:与程序可达性属性相关的布尔变量的个数占所有相关变量的比例,这里是百分比比例,通过取整成为0-100之间的整数值。6.relevant_addressed_vars_ratio:与程序可达性属性相关的取址变量的个数占所有相关变量的比例,同样是百分比。7.number_of_relevant_variables:程序中所有与可达性相关的变量个数。8.number_of_addressed_variables:程序中取址变量的个数。程序语义特征体现了程序中的部分语句的信息,如右值函数的个数。也包括变量用途的信息,如作为布尔条件用的整型变量的个数。变量的用途比变量的类型更加精确,也能节省验证算法的一些内部表示。程序语义特征有:1.program_requires_alias_handling:程序中是否出现了需要进行别名分析的变量(比如指针变量,数组等)。2.number_of_righthand_side_functions:程序中函数返回值被赋值给变量的函数个数,且该变量与可达性分析相关。3.number_of_intbool_vars:程序中整型变量中有作为布尔条件用的变量的个数。4.number_of_int_equal_partitions:程序的抽象分区只有用作等价对比的整数的分区的个数。5.number_of_int_equal_vars:程序中仅仅被整数赋值或者用等号与整数做对比的变量,不涉及加减乘等操作的变量个数。6.number_of_int_add_vars:程序中仅仅进行简单操作的变量个数,加减,比较,异或等。7.number_of_int_overflow_vars:程序中进行了可能会引起溢出的操作的变量个数,比如加减乘除,取模,移位等。&number_of_assumed_variables:程序中出现在assumption的变量个数。9.number_of_assigned_variables:程序中出现在赋值的左边的变量个数。而当程序在迭代验证的过程中,我们能从验证工具,也就是cpachecker中抽取出动态可达图和相关cpa算法的统计信息。根据他们的特点,里面有时间类特征,和非时间类特征,而非时间类特征根据数据类型又有整数和布尔型特征。因为动态特征大部分来源于本文在cpachecker对各个算法的运行状态的统计,因此,可以根据特征来源进行划分。动态特征可以包括:精化算法类特征、可配置程序分析cpa算法类特征、基础算法类特征、精度调整类特征、插值类特征、以及数据类特征。第一大类特征来源于精化算法,主要有通用精化类特征,值分析精化类特征,谓词分析精化类特征,精化策略类特征特征,谓词抽象精化策略类。精化算法类中的特征包括了不同抽象域在进行精化时的一些时间消耗,以及他们的影响范围,即被精化的节点的个数等。⑴通用精化类(genericrefiner)特征:time_completing_refinement_[accumulated/max]:无论是使用值分析还是谓词分析,抽象精化的时间的累积值和每次累积的过程中最大的值。number_of_refinements_count:cegar算法运行过程中总共的抽象精化的次数。⑵值分析精化类(valueanalysisrefiner)特征:number_of_root_relocations_count:在cpa算法分析过程中,可能会对需要精化的节点所组成的子树的根进行重定向,比如,如果是需要全局精化,那这个根节点就是最初的初始节点。这里是统计了重定向的次数,跟cpachecker中的配置相互对应。number_of_similar_repeated_refinements_count:在需要精化的子树的根节点个数是1的情况下(一般也是1,因为是只需要找到一条反例路径),看根节点增加的精度是否在历史上出现过,是的话,个数就加1。.number_of_previous_refinement_ids:所有被精化过的根节点的个数,同时考虑节点被精化时的精度,只考虑不重复的计数。(3)谓词分析精化类(predicatecparefiner)特征:time_for_pred_refinement_[accumulated/max]:这里是使用谓词分析的时间累积值和最大值。time_error_path_post_processing_[accumulated/max]:谓词分析里面对错误分析进行后处理的累积时间和最大时间的统计。time_for_path_formulas_extraction_[accumulated/max]:谓词分析里面抽取路径公式的累积时间和最大时间的统计。length_of_target_path_blocks_[max/min/avg]:谓词分析里面抽象的错误路径中块的个数的统计值,包括最大值,最小值,平均值,块的概念则是来自于可调块编码。从一定程度上反映了arg的增长速度。⑷精化策略类(refinementstrategy)特征:length_of_refined_path_in_blocks_[max/min/avg]:进行谓词分析的时候,在计算出来路径和插值后,实际被精化的路径的长度,这里谓词分析中用了块编码。number_of_affected_states_[max/min/avg]:每一次谓词精化的时候,实际精度有变化的状态的个数的统计。(5)谓词抽象精化策略(predicateabstractionrefinementstrategy):time_for_predicate_creation_[accumulated/max]:在谓词分析中,对单个状态,依据插值计算新的谓词,作为新的精度加进来的时间的累积与最大值。time_for_precision_update_[accumulated/max]:在谓词分析中,对根节点,更新精度的时间的累积与最大值。time_for_arg_update_[accumulated/max]:谓词精化过程中更新arg的总时间,在进行谓词分析的时候,求出了被精化的根节点和相应的新增的精度之后,更新整个arg的时间,就是移除掉以这个节点为根的所有子树节点,,以及被这些子树节点覆盖的节点,调整这些节点的精度,并重新加入到候选列表里面的过程。第二个变量的意思是,在多次的谓词精化过程中,耗时最长的时间,以毫秒计算。number_of_refs_with_location_based_cutoff:在谓词精化的策略中,当找到了所有受影响的arg的状态后(是一个集合,是根据路径逆序的),需要找到从哪一个状态开始精化,然后从这个状态作为精化的起始节点,重新计算以它为根的子树上的节点上的精度。这里有两种策略,一是直接选第一个状态,也就是正常arg路径的最后一个状态,第二种是从第一个状态开始往上走,选择跟她是同一个cfa结点的位置最高的arg的状态,也就是最接近根节点的。选择第一种策略的前提是,路径的最后一个状态有新的谓词被计算出来,否则选最接近根节点的,这里对应了前缀选择的时候,对枢轴长度的评估,要么选最深的,要么选最浅的。枢轴指,从根节点到达当前的节点,是不可满足的。第二类特征来源于不同的cpa算法,主要有可配置值分析算法和可配置谓词分析算法。值分析算法主要是值分析中的确定性等级值,可以直接反映值分析的难度。谓词分析算法同样通过谓词抽象域的几个算子被调用的信息反应谓词分析的难度。(1)可配置值分析算法(valueanalysiscpa)特征:ratio_of_determinism:值分析中的确定性等级值,即当前跟踪的变量占所有变量的百分比,跟踪的变量越多,则百分比越大。⑵可配置谓词分析算法(predicatecpastatistics)特征:number_of_false_result:谓词分析中计算抽象后置节点出现了false的次数,也就是在计算过程中计算出节点不可达的次数。number_of_strengthen_sat_checks:谓词分析中增强的sat检测的次数。number_of_coverage_checks:谓词分析中对节点覆盖关系检测的次数。number_of_bdd_entailment_checks:谓词分析中使用bdd的技术进行覆盖关系检测的次数。number_of_smt_[total/trivial/cached]_sat_checks:谓词分析中用计算迁移关系的时候,进行smt检测的次数,及其中简单的和被缓存的的sat检查的个数。size_of_abe_block_[max/min/avg]:谓词分析中可调块编码的块大小的统计,其中的最大值,最小值和平均值。number_of_predicates_discovered:谓词分析中发现的不同的谓词的个数。基础类特征,主要有cegar算法和javabdd管理类的特征。cegar算法是对整个cegar的流程的一些时间统计和精化次数的统计,以及精化前后arg的大小的统计。cegar算法是基于值分析精化和谓词分析精化的,整个crgar算法的时间同时会算上其他开销。另外,cegar算法中还统计了不同抽象域精化成功和失败的次数。因此cegar算法可以一定程度体现之前选择的优劣。javabdd管理类是对谓词分析中谓词表示,计算等的统计。可以体现每次计算出的谓词的复杂程度。(1)cegar算法(cegaralgorithm)特征:time_for_cegar_algorithm:cegar算法的总时间。time_for_refinements:抽象精化的总时间。number_of_successful_refinements:cegar算法运行过程中总共的成功的精化次数。number_of_failed_refinements:cegar算法运行过程中总共的失败的精化次数。size_of_reached_set_[before/after]_refine_max:cegar算法里面对可达状态集合的大小在精化前和精化后的统计。(2)javabdd管理类(javabddregionmanager)特征:time_for_bdd_node_cleanup_[accumulated/max]:谓词分析中清除bdd节点的累积时间和最大时间,bdd的解释可以看后文。number_of_bdd_nodes:bdd是用在谓词抽象里面的,是谓词的一种表示,也是一种编码方式,另外一种是smt的编码。bdd表达的谓词语义是true或者false两种情况,但是smt表达的语义可以更丰富,比如大于等于这种关系,因此bdd可以说是更加抽象的一种表示,所以bdd的统计情况可以从一定程度上反应谓词抽象的难度。这里是指谓词分析中用bdd表示的节点的个数。size_of_bdd_node_cleanup_queue_[max/min/avg]:bdd节点在谓词分析的过程中,会根据抽象的情况进行相应的创建和清除,这里是指用于清除的队列,里面节点个数的最大值,最小值,平均值。精度调整类特征,包括值分析精度调整和谓词分析精度调整的信息。精度调整是因为程序比较大的时候,需要进行块编码,在不同类型块中会用不同的精度信息。在动态精度调整的设置下,算法会根据运行情况,选择性地把计算出的新精度加到不同的arg结点上。因此精度调整可以体现不同抽象域的算法对arg中节点精度调整的范围和计算消耗。(1)值分析精度调整(valueanalysisprecisionadjustment)特征:number_of_abstraction_computations_in_value:在值分析中进行抽象计算的次数,这个也跟预先的配置相关,比如,是在每个分支抽象,还是在合并节点或者是函数和循环进行抽象。time_for_abstraction_computation_[avg/sum/max]:在值分析的抽象精化进行精度调整的过程中,抽象计算的时间的统计。time_for_path_thresholds_[avg/sum/max]:在值分析的精度调整中,如果当前路径对某些跟踪的变量,它们的赋值超过一个阈值,则会强制对这些变量进行抽象。这里是对强制抽象计算所消耗时间的统计。(2)谓词分析精度(predicateanalysisprecisionadjustment)特征:number_of_abstractions:谓词分析中总共进行抽象计算的个数。ratio_of_abstractions_percentage:谓词分析抽象计算进行占总的后置计算的比例。number_of_abstraction_was_reused:谓词分析中抽象被重用的个数。number_of_abstraction_because_of_[function_entry_or_exit/loop_head/join_nodes/threshold/target_state]:谓词分析中抽象计算的原因分别是函数出入口,循环头,合并节点,阈值,目标状态的个数。number_of_[empty/false]_precision:谓词分析中为空的精度节点个数和为false的个数。number_of_abstractions_cached:谓词分析中被缓存的抽象计算的个数。number_of_[cartesian/boolean]_abstraction_was_used:谓词分析中由笛卡尔抽象完成抽象计算的个数,和由布尔抽象完成抽象计算的个数。插值类特征包括从通用路径插值类获取的信息,通用路径插值类中包括了值分析的插值信息的插值信息以及计算这些插值消耗的时间。另外还有值分析中对不可满足路径的前缀进行计算和选择的时间。所以该类可以一定程度反映值分析进行插值计算的难度。谓词分析插值类则包括了谓词分析在进行插值序列计算时的一些特征,通过插值序列中前缀为true的长度,和后缀为false的长度来体现插值序列的实际有效宽度。另外,通过插值序列中简单和不简单的实际的插值统计也可以体现插值计算的难度。(1)通用路径插值类(genericpathinterpolator)特征:time_for_interpolation_[accumulated/max]:进行谓词分析精化的时候,如果用基于路径的算法(还有一个算法是基于边的)计算插值,时间的累积值和最大值。number_of_interpolation_in_value:值分析中插值的个数,值分析的插值不需要调用昂贵的smt求解器,而是实现在cpachecker内部的。number_of_interpolation_queries_[max/min/avg]:在值分析中精化的时候,插值查询的个数,这跟用基于边的算法还是基于路径的算法有关,基于路径的算法每次只会查询1次,但是基于边的算法需要进行更具体的计算。所以基于边的算法是更加精确的,基于路径的算法是更加快速的。size_of_interpolant_in_value_[max/min/avg]:值分析求出的插值的大小的统计。number_of_sliced_prefixes:值分析中抽出的不可满足的路径前缀的个数。time_for_extracting_infeasible_sliced_prefixes_[accumulated/max]:值分析中抽出不可满足的路径前缀的累积时间和最大时间。time_for_selecting_infeasible_sliced_prefixes_[accumulated/max]:值分析中选择不可满足的路径前缀的累积时间和最大时间。(2)谓词分析插值类(predicateanalysisinterpolator)特征:length_of_path_with_interpolant_true_[max/min/avg]:在每次谓词精化中,对路径(或者是路径的前缀)进行插值计算后,前面的插值为true的状态的个数统计。length_of_path_with_interpolant_nontrivial_[max/min/avg]:在每次进行谓词精化中,对路径(或者是路径的前缀)进行插值计算后,插值序列中不是简单的插值的个数,即不是ture或者false的插值的个数统计。length_of_path_with_interpolant_false_[max/min/avg]:在每次谓词精化中,对路径(或者是路径的前缀)进行插值计算后,后面的插值为false的状态的个数统计。number_of_different_nontrivial_interpolants_along_paths_[max/min/avg]:在每次谓词精化中,对路径(或者是路径的前缀)进行插值计算后,与路径中上一个状态的插值的是不同的,且是非简单的插值对应的状态的个数统计。number_of_equal_nontrivial_interpolants_along_paths_[max/min/avg]:在每次谓词精化中,对路径(或者是路径的前缀)进行插值计算后,与在路径中上一个状态的插值是相同的,且是非简单的插值所对应的状态的个数统计。数据类是对关键数据结构等的信息统计,目前有反例信息类。反例信息类能反应当前反例包含的一些信息,从侧面可以体现当前反例路径的难度。(1)反例信息类(counterxaexmple)特征:domain_type_score_min:计算反例路径在值分析中的的所有不可满足前缀,计算每个前缀的域分数,这里是其中最小的域分数。分数越大,意味着值分析跟踪的变量会越复杂,分数到达极大值,就意味着值分析会包含循环计数器变量。其中,带有”time”的特征都是时间类特征,时间类特征相对于其他特征会有更大的范围变化性。因为一些算法是多项式甚至指数级别的复杂度,时间类特征在不同的迭代轮次会相差较大。因此,如何处理时间类特征,让它不因自己取值大就占据更多的权重是需要在特征处理考虑的问题。而其他就是非时间类特征。非时间类特征大部分是对cpa算法和cegar算法中其他非时间类型特征的统计,以各种子算法的运行次数,及算法能够增加的新的数据的个数居多。因为大部分是整数型的特征,因此也主要是体现了量级的关系。更加重要的是,这些特征往往也能体现过去的选择中,算法的一些非时间类消耗,比如谓词分析中发现的不同的谓词的个数和值分析求出的插值的大小能分别体现这两种分析方式之前的处理难度。如图2所示,是cpachecker进行程序验证时的框架,也是我们的特征抽取框架。特征抽取流程依赖于整个cpachecker的验证过程,同时在一些关键的类里引入了统计的类,这些类会被集中管理起来,当向智能体(agent)发送当前状态时,就会通过集中管理的类分别调用这些统计类的统计方法,从而收集程序的统计特征。具体流程是,程序源代码通过解析器解析和预处理后,会用来构建程序控制流图cfa,程序控制流图被构建之后会向全局的程序特征管理类发送消息,这时候管理类就通过调用cfa的统计类获得cfa构建的统计信息和cfa的一些静态信息,将这些进行存储。cpa算法通过读取相关的配置文件构建规格cpa,指定程序要验证的属性。由于本实施例采取了组合cpa的配置,又会依次构建出位置cpa,调用栈cpa,函数指针cpa,值分析cpa,谓词分析cpa。而值分析cpa和谓词分析cpa的类中的统计类实现了我们引入的额外的针对强化学习特征抽取的接口,在这些cpa算法运行的时候会更新并存储统计信息,而在之后的管理类调用过程中返回这些统计信息。cegar算法则依赖于cpa和cfa进行构建,在cegar算法中也有实现了为强化学习的特征抽取而服务的统计接口的类实例,每一轮cegar都会被调用返回最新的关于cegar的统计信息。同时cegar算法会和精化算法进行交互。本实施例采用的是组合精化算法,即由值精化算法和谓词精化算法组合而来的,可在组合精化算法的逻辑中实现相应的动态逻辑,比如当前轮次优先采用哪种精化算法。在这些精化算法中,也有对应的特征统计的接口实现。在本发明实施例中,还可以对各程序特征进行预处理,各程序特征首先经过特征分类器,分类器将程序特征分为以下几类:1.布尔类型,值只出现了0和1。2.时间类型,通过时间的统计得出的数据,会反映算法的时间复杂度。在一些类型上,比如反例精化算法,会有指数级增长的趋势。3.小整数类型,数值范围在0-100之间,多来源于一些个数的统计。4.大整数类型,数值范围超过100的,比如bdd跟踪变量的个数,会随着arg的逐渐增长有比较大的值出现。之后,如果特征被分为布尔类型,则不做任何处理。否则,判断当前的配置,是否需要对数据升维,不升维的话就根据之前的分类结果,选择相应的处理方式,这里的处理方式是一对一的。时间类型会被取自然对数,小整数会被取成10个桶,大整数也会被取对数或是分桶。这里的对应关系,都是通过查询字典的方式得到,而处理方法也是可配置的。如果需要对数据升维,则对非布尔的类型都会链接上所有的数据处理方法。之后,执行模块会对所有特征执行被链接上的方法,并返回处理后的特征。值得注意的是,这里,之所以有数据升维的选项,是方便做对比实验。而我们实验发现,特征维度较少,即不进行升维的时候,强化学习的神经网络误差降低速率会比较小,因此之后都默认采用了数据升维的方式。而数据升维,正是因为对一个特征采取了多个处理方法,得到了不同结果所导致的。在获取到程序特征之后,通过对非布尔类型的程序特征进行升维处理,能够在基于神经网络模型确定抽象域时,降低神经网络模型的误差降低速率,提高抽象域确定的准确性。s130:将第一子程序的下一子程序作为当前子程序,将第一程序特征作为当前程序特征。s140:将当前程序特征输入预先训练得到的神经网络模型中,得到当前程序特征对应的当前抽象域;神经网络模型为预先根据各样本子程序,以及各样本子程序对应的样本抽象域训练得到的。在本发明实施例中,为了提高抽象域确定的速率和准确性,可以基于强化学习的方法来确定抽象域。具体的,可以预先训练得到神经网络模型,进而在进行抽象域确定时,将提取到的当前程序特征输入神经网络模型中,即可输出该当前程序特征对应的当前抽象域。具体的,上述神经网络模型的训练过程可以包括以下步骤:构建初始网络模型;获取各样本子程序,并运行各样本子程序,在各样本子程序运行过程中统计得到各样本子程序对应的样本程序特征;确定各样本子程序对应的样本抽象域;将各样本程序特征,以及各样本子程序对应的样本抽象域输入初始网络模型中,对初始网络模型进行训练得到神经网络模型。可选的,运行各样本子程序,在各样本子程序运行过程中统计得到各样本子程序对应的样本程序特征之后,还可以对各样本程序特征进行分类,确定所有的非布尔类型的目标样本程序特征;判断是否扩展所有特征;当确定扩展所有特征时,对每个目标样本程序特征进行升维处理;当确定不扩展所有特征时,获取预定类型的目标样本程序特征,并对所获取的目标样本程序特征进行升维处理。具体的,对每个目标样本程序特征进行升维处理的步骤可以包括:针对时间类型的目标样本程序特征,对该目标样本程序特征进行取自然对数处理;针对小整数类型的目标样本程序特征,对该目标样本程序特征进行分桶处理;小整数类型的目标样本程序特征为数值范围在0-100之间的特征;针对大整数类型的目标样本程序特征,对该目标样本程序特征进行取自然对数或分桶处理;大整数类型的目标样本程序特征为数值大于100的特征。这里之所以有数据升维的选项,是方便做对比实验。而我们实验发现,特征维度较少,即不进行升维的时候,强化学习的神经网络误差降低速率会比较小,因此之后都默认采用了数据升维的方式。而数据升维,正是因为对一个特征采取了多个处理方法,得到了不同结果所导致的。在获取到程序特征之后,通过对非布尔类型的程序特征进行升维处理,能够在基于神经网络模型确定抽象域时,降低神经网络模型的误差降低速率,提高抽象域确定的准确性。其中,上述初始网络模型的结构可以为已知的任一种结构,只要能实现根据输入的程序特征,输出对应的抽象域的功能即可,本发明实施例不对其结构作具体限定。确定各样本子程序对应的样本抽象域时,可以对各样本子程序对应的各抽象域进行验证后,选取教优的抽象域作为样本抽象域。具体的,将各样本程序特征,以及各样本子程序对应的样本抽象域输入初始网络模型中,对初始网络模型进行训练得到神经网络模型的步骤可以包括:将各样本程序特征,以及各样本子程序对应的样本抽象域输入初始网络模型中,基于q-学习算法对初始网络模型进行训练,当初始网络模型的激励函数满足预设条件时,将当前的初始网络模型确定为神经网络模型。强化学习是一种智能体agent通过尝试和犯错来与环境environment通过交互来学习如何进行行动从而实现一个目标的算法。在强化学习中,状态的迁移过程符合马尔科夫性质,即下一个状态仅仅依赖于当前状态和当前执行的动作,一个策略是一个从状态到动作的映射,他确定了智能体在状态下会执行的动作。而智能体的通常目标是是学习一个策略,该策略可以最大限度地提高其长期行动的累积奖励而不仅仅是即时奖励。策略记录了在给定状态下具有最高预期长期奖励的动作,因此智能体只需要基于这个策略来做动作的选择和执行,从而得到期望的最高累积奖励。在抽象域选择问题中,智能体agent就是本发明实施例的抽象域选择算法,实际存在于python端;环境environment对应着整个验证框架,实际对应着cpachecker这个验证框架;智能体与环境交互,对应着python端的算法与cpachecker的套接字通信;而智能体能感知到的环境的状态,对应着上述从cpachecker端收集并处理的特征向量,智能体能产生的动作,就是选择一个抽象域并进行反例的抽象精化。在本实施例中,只有两个可以选择的动作,分别是值分析抽象和谓词分析抽象。而对于激励函数,也即q函数,的设计,需要考虑抽象精化算法的结果和对环境造成的影响。而智能体可以通过强化学习学到的策略,就是在当前状态下,应该选择哪一个抽象域,这样可以获得最大的累积长期激励,长期激励应当给验证成功且用时越短的策略更多的分数。强化学习问题能够被建模为mdp(markovdecisionprocesses,马尔科夫决策过程)问题,从而通过贝尔曼方程通过动态规划的方式解决,也叫基于模型的强化学习。但是现实问题的强化学习问题往往不能获取mdp问题中的转移概率,所以解决基于模型的强化学习方法的值迭代和策略迭代算法不能用来解决此类问题。需要用一些近似的方法来替代。而本实施例使用的是基于值迭代的近似方法。q学习算法则是最原始的一种算法,也是一种基于查表的学习算法,这张表即q-table,存储了在各个状态下执行不同动作会获得的激励,一旦计算并存储了这张表,之后选择的时候只需要查表,并选择当前价值最大的那个动作去执行,因此奉行的是贪心的策略。根据上面的描述可知,q-table是按行列存储的表,行代表了状态的个数,列代表了动作的个数。对于状态和动作都有限的强化学习问题,可以证明是能通过q-table得到最优解的。而对于状态无限,动作有限的强化学习,就可以通过动态增加行来解决。如果对于动作无限的强化学习,则需要其他算法去解决。而本实施例当前的问题是状态无限,动作有限的方式,因此需要用升级版本的q-学习算法来解决。q-学习算法计算表的方法是先全0初始化,然后不断选择并执行动作获得与环境的反馈,再不断更新q-table,直到收敛的过程。q-table存储的q(s,a)表示的是在状态s下,采取动作a的长期期望激励。贝尔曼方程给出的长期期望激励的计算方式是一个给定动作的长期期望激励等于在当前状态s执行动作a后获得的即时激励r加上转移到的状态s’后的最优未来期望激励,因此真实的激励可以被表示为q(s,a)=r+γmaxq(s',a')。公式中引入了折现因子γ,就允许人为决定相对于当前的即时激励,未来的期望激励的相对重要性。γ的取值范围是0到1之间,如果设为0时则表示只关心即时激励,设为1则表示未来的期望激励跟即时激励一样重要。那么更新的规则就用到了和监督学习类似的方式,因为真实的激励是不知道的,最初只知道当前的预期激励,也就是表格当前的值,所以通过求两者的误差和学习率相乘进行更新,规则如下:q(s,a)=q(s,a)+α(q'(s,a)-q(s,a))。另外,在q-学习算法中,还有探索与利用的问题,因为原始算法倾向于选择在当前状态和学习到的信息下,最好的方案,而因为当前学习到的信息可能还不足,所以可能会导致当前的选择不太准确,而后面需要比较多的迭代次数达到一个稳定值。因此,通过引入探索因子,就会选择在当前看来并不是最好的方案,由此可能更快找到最优方案。而这个探索因子就是ε,即每次有ε的概率选择当前q-table中最大的动作,有1-ε的概率选择随机策略。q-学习算法能够被用来在状态-动作对中学习q函数。但是通常的状态空间都会很大,导致无法显式计算出对每一个状态动作对的q函数,因此q函数在这种情况下只能通过近似去逼近。对于本文的问题,状态空间也是指数级别的。因此深度q学习算法被提了出来,他的作用是用神经网络拟合q-table。当神经网络训练完成后,输入就是当前状态,输出是当前状态对应的每个动作的q值。那么问题的关键就在于深度q学习算法怎么进行神经网络的训练,它的原理也与q学习算法如出一辙,即通过预期的q值和真实的q值的误差进行反向传播,更新网络参数。相比于传统的q学习算法,基于深度学习的q学习算法最大的不同在于引入了备忘录机制,也就是一种经验回放。它的逻辑就是不断进行实验,在实验的每一步中都会计算出要存入备忘录的信息,这个信息也叫样例,是一个四元组,包括当前状态下各种动作的q值,即φt,当前采取的动作at,当前采取动作获得的回报rt,下一个迁移到的状态下各种动作的q值φt+1,然后从备忘录中每次采样出一部分的样例,称为一个minibatch,再计算出这些样例所对应的真实长期期望激励,最后再利用神经网络进行梯度下降的更新。这里计算真实长期期望激励需要判断下一个状态是否是终止状态,如果是终止状态则只有当前的即时回报了。之所以要引入备忘录机制,是因为最初的样本是按照时间顺序构造的,是比较相关的样本,有些违背马尔科夫性质,容易导致训练很难收敛,因此通过备忘录机制进行随机采样可以在一定程度上打破这种相关性,让神经网络的误差更容易收敛。深度q学习算法方式的缺点就是训练是离线的方式,不能在线的进行。不过这也对本实施例的实验带来了便利,因为验证一次程序的代价是比较大的,本实施例可以离线地通过验证程序保存下来所有的回合,再对这些回合的数据进行训练,实际过程中,本实施例生成训练需要用的回合数据需要十几个小时,但是离线的训练几个小时就可以完成。在应用强化学习比较多的游戏环境,每次智能体执行一个动作之后环境都能给出显式的反馈,比如吃到一个苹果得1分,遇到到1个怪物减去2分。这样的分数可以作为即时回报来考虑,但是在本实施例的实验中,没有这样的显示反馈,因此需要人为去设计,而从经验看来,激励函数的设计对整个强化学习的效果也有比较大的影响。这里,本实施例考虑以实验中选择的精化算法的执行结果为准,包括值分析精化算法,和谓词分析精化算法。在本实施例的设计中,如图3所示,原始激励设计主要考虑了3种情况:1.当前选择的抽象精化算法即精化器1能解决当前伪反例,即抽象域的精化的结果是确认当前反例是伪反例,这时抽象域肯定消除了这个反例,那么本实施例给出的原始激励是1,定义为good。2.当前选择的抽象精化算法即精化器1不能解决当前伪反例,即抽象域的精化的结果是认为当前反例可能是真反例,但是再次通过其他抽象精化算法即精化器2可以消除。那么本实施例给出的原始激励是-1,定义为bad。3.当前选择的抽象精化算法即精化器1不能解决当前伪反例,其他抽象域也不能解决。那么本实施例给出的原始激励是0,定义为normal。4.当前选择的抽象精化算法通过精化算法后,证明了程序的正确性或错误性,程序验证终止,那么本实施例给出的原始激励是5,定义为well-done。5.当前选择的抽象精化算法在精化过程中,造成程序验证超时而被终止,那么本实施例给出的原始激励是-5,定义为timeout。为了方便对不同的激励策略进行调优,本实施例将上述激励称为原始激励,是直接由cpachecker端返回的,之后本文在python端对激励进行了重构,重构策略通过重新映射来实现。见下表所示:通过以上的激励函数重构,本文可以实现几种不同类型的激励策略,主要有奖惩一致,即对于程序验证成功的激励和超时的惩罚绝对值相等,abs(wscore)=abs(tscore);奖励驱动制,即对于程序验证成功激励的绝对值要大于超时的惩罚,abs(wscore)>abs(tscore);惩罚驱动制,即对于程序验证成功激励的绝对值要小于超时的惩罚,abs(wscore)>abs(tscore)。实验结果发现惩罚驱动效果更好,找到的最好策略经过测试是wscore=5,tscore=-15。对此得出的经验是,在本实施例的实验中,如果决策算法不能很好地给出当前状态选择哪一个抽象域好,那么会影响之后的验证算法的计算,比如应该选择值分析的时候选择了谓词抽象,则很可能会导致之后的分析超时。因此,对于超时的惩罚很重要,超时的惩罚要大于奖励,这样才可以学到更优的策略,也能进一步提高本实施例解决其他例子的平均时间。如图4所示,是强化学习的训练流程。首先是通过cpachecker和原始智能体agent的信息交互,会存下中间交互的消息日志,这里的交互信息是agent存下每一个程序跑10次的回合信息,这些回合信息包括未经处理的状态特征,动作,原始激励等。原始agent是不带神经网络决策的agent,只会返回一个随机的选择,但是cpachecker可以选择不执行这个随机的选择,而选择基准算法的建议。在有了消息日志后,通过信息解析器将信息进行解析,同时程序会读入其他参数配置文件信息,并用配置文件处理器进行解析和读取,之后根据配置文件的信息构造相应的策略组合类,策略组合类包括三种策略:特征预处理策略、神经网络架构策略、以及激励处理策略。之后程序根据特征预处理策略处理信息日志中对应的原始特征信息,并将处理过程中生成的参数文件进行保存。再根据网络架构策略构建相应的神经网络,三层神经网络或五层神经网络,以及带relu激活的和带sigmoid激活的网络。激励策略主要会根据传入的配置文件调整初始激励的映射信息值,从而形成不同的激励策略。之后就进入了神经网络的训练过程,训练中依赖的超参数也会在配置文件中体现,从而反应到训练的控制上,重要的参数有γ值,epoch的大小等。神经网络训练过程中也会不断写入检查点,以方便后续的测试和恢复训练。如图5所示,是强化学习的测试过程。初始时,系统会读入测试的配置文件信息,并通过配置处理函数进行处理,形成相应的特征处理策略,同时会读入之前存好的神经网络模型并进行模型的构造。同时,启动消息监听。在有状态信息传递过来之后,经过消息的解析,会形成初始的特征。之后预处理器则根据特征处理策略和之前训练阶段存下的预处理参数对测试阶段的信息进行同样的特征预处理。最后就是送入已经恢复好的网络,求得不同动作的q值,再根据q值最大的返回相应的动作。再通过消息发送器返回给cpachecker端。强化学习的智能体agent与环境cpachecker的信息交互过程为,cpachecker正如之前定义的,作为强化学习里面的环境,负责给agent的行为进行反馈。以及主动给agent发送消息了解环境状态。最初,程序验证开始,cpachecker会负责发送一个(program,start)的消息,表示已经开始验证程序program,这时候的program会包含被验证程序的基本信息,包括程序名和上述介绍过的静态信息。agent接受到后会记录信息,并与cpachecker端建立起socket连接,之后返回确认消息。之后,随着验证过程的进行,在第一次进入cegar的流程后,cpachecker端会调用相应的统计信息收集类作为状态的特征表示,其中包括当前错误路径的一些信息。并发送给agent,请求agent选择一个抽象域,值抽象或者谓词抽象,来解决当前的错误路径。agent经过计算后,会给出一个建议的选择,之后cpachecker端会返回他最终做的决策,以及该决策的即时结果,即是否消除了反例,给agent以记录。同样agent也会返回确认消息。如果当前选择的抽象域成功消除了反例,并且也证明了程序的正确性,则验证成功了,cpachecker随机发出特殊的信号以表明验证结束,在得到agent的确认后,便主动关闭连接了。s150:基于当前抽象域,对当前子程序进行验证,并在验证过程中统计得到当前子程序对应的当前程序特征。需要说明的是,在本发明实施例中,为了便于区分,将不同子程序对应的程序特征分别进行了命名,但是,本实施例中提到的每个程序特征均与前述第一程序特征相同,均包括前述所有的静态特征和动态特征,此为本发明实施例的发明点之一。s160:判断是否存在未验证的子程序;当存在未验证的子程序时,将当前子程序的下一子程序作为当前子程序,返回执行步骤s140,将当前程序特征输入预先训练得到的神经网络模型中,得到当前程序特征对应的当前抽象域的步骤。通过上述循环,可以对每个子程序均进行验证,从而完成对整个待验证程序的验证。由上述内容可知,本实施例可以基于强化学习的方法,在获取到各子程序的程序特征后,通过预先训练得到的神经网络模型确定各抽象域,神经网络模型具有计算速度快的特点,因此,可以提高抽象域确定的效率。图6为本发明实施例提供一种基于强化学习的程序验证装置的结构示意图,所述装置包括:程序获取模块610,用于获取待验证程序;所述待验证程序包括多个子程序,各所述子程序具有先后执行顺序关系;特征提取模块620,用于运行所述多个子程序中的第一个子程序,在所述第一个子程序运行过程中统计得到所述第一个子程序对应的第一程序特征;程序处理模块630,用于将所述第一子程序的下一子程序作为当前子程序,将所述第一程序特征作为当前程序特征;抽象域确定模块640,用于将所述当前程序特征输入预先训练得到的神经网络模型中,得到所述当前程序特征对应的当前抽象域;所述神经网络模型为预先根据各样本子程序,以及各所述样本子程序对应的样本抽象域训练得到的;程序验证模块650,用于基于所述当前抽象域,对所述当前子程序进行验证,并在验证过程中统计得到所述当前子程序对应的当前程序特征;程序判断模块660,用于判断是否存在未验证的子程序;当存在未验证的子程序时,将所述当前子程序的下一子程序作为当前子程序,触发所述抽象域确定模块。可选的,所述装置包括:模型构建模块,用于构建初始网络模型;样本获取模块,用于获取各样本子程序,并运行各所述样本子程序,在各所述样本子程序运行过程中统计得到各所述样本子程序对应的样本程序特征;样本抽象域确定模块,用于确定各所述样本子程序对应的样本抽象域;模型训练模块,用于将各所述样本程序特征,以及各所述样本子程序对应的样本抽象域输入所述初始网络模型中,对所述初始网络模型进行训练得到所述神经网络模型。可选的,所述模型训练模块,具体用于:将各所述样本程序特征,以及各所述样本子程序对应的样本抽象域输入所述初始网络模型中,基于q-学习算法对所述初始网络模型进行训练,当所述初始网络模型的激励函数满足预设条件时,将当前的初始网络模型确定为所述神经网络模型。可选的,所述装置还包括:特征分类模块,用于对各所述样本程序特征进行分类,确定所有的非布尔类型的目标样本程序特征;特征判断模块,用于判断是否扩展所有特征;特征处理模块,用于当确定扩展所有特征时,对每个所述目标样本程序特征进行升维处理;当确定不扩展所有特征时,获取预定类型的目标样本程序特征,并对所获取的目标样本程序特征进行升维处理。可选的,所述特征处理模块,具体用于:针对时间类型的目标样本程序特征,对该目标样本程序特征进行取自然对数处理;针对小整数类型的目标样本程序特征,对该目标样本程序特征进行分桶处理;所述小整数类型的目标样本程序特征为数值范围在0-100之间的特征;针对大整数类型的目标样本程序特征,对该目标样本程序特征进行取自然对数或分桶处理;所述大整数类型的目标样本程序特征为数值大于100的特征。由上述内容可知,本发明实施例提供的基于强化学习的程序验证装置,能够基于强化学习的方法,在获取到各子程序的程序特征后,通过预先训练得到的神经网络模型确定各抽象域,神经网络模型具有计算速度快的特点,因此,可以提高抽象域确定的效率。上述装置实施例与方法实施例相对应,与该方法实施例具有同样的技术效果,具体说明参见方法实施例。装置实施例是基于方法实施例得到的,具体的说明可以参见方法实施例部分,此处不再赘述。本领域普通技术人员可以理解:附图只是一个实施例的示意图,附图中的模块或流程并不一定是实施本发明所必须的。本领域普通技术人员可以理解:实施例中的装置中的模块可以按照实施例描述分布于实施例的装置中,也可以进行相应变化位于不同于本实施例的一个或多个装置中。上述实施例的模块可以合并为一个模块,也可以进一步拆分成多个子模块。最后应说明的是:以上实施例仅用以说明本发明的技术方案,而非对其限制;尽管参照前述实施例对本发明进行了详细的说明,本领域的普通技术人员应当理解:其依然可以对前述实施例所记载的技术方案进行修改,或者对其中部分技术特征进行等同替换;而这些修改或者替换,并不使相应技术方案的本质脱离本发明实施例技术方案的精神和范围。当前第1页12当前第1页12
当前第1页1 2 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1