在Python中实现贪婪排名算法的教程


Posted in Python onApril 17, 2015

 在较早的一遍文章中,我曾经提到过我已经写了一个属于自己的排序算法,并且认为需要通过一些代码来重新回顾一下这个排序算法。

对于我所完成的工作,我核实并且保证微处理器的安全。对非常复杂的CPU进行测试的一个方法就是创建该芯片的另一个模型,其可以用来产生在CPU上运行的伪随机指令流。这所谓的ISG(指令流产生器)能够在很短的时间内创建几千(甚至几百万)个这样的测试,通过某种方式,使其可以巧妙地给出一些对将在CPU上执行的指令流的控制或操纵。

现在对这些指令流进行模拟,可以通过每一个测试实例花费的时间获取到CPU的那一部分被使用了(这叫做被覆盖)的信息,并且ISG所产生的的过个测试可能会覆盖CPU的同一个区域。为了增加CPU的整体覆盖范围,我们启动一个被称作复原的行为——所有的测试都运行,并且它们的覆盖范围和花费的时间将被存储起来。在这次复原的最后,您可能会有几千个测试实例只覆盖了CPU的某一部分。

如果你拿着这个复原测试的记过,并且对其进行排序,你会发现这个测试结果的一个子集会给出它们覆盖了CPU的所有部分。通常,上千的伪随机测试可能会被排序,进而产生一个只有几百个测试的子列表,它们在运行时将会给出同样的覆盖范围。接下来我们经常会做的是,查看CPU的哪个部分没有被覆盖,然后通过ISG或其它方法在产生更多的测试,来试图填补这一空白。再然后会运行一次新的复原,并且循环得再一次进行排序来充分使用该CPU,以达到某个覆盖范围目标。

对测试进行排名是复原流程的一个重要部分,当其进行地很好时你可能就会忘记它。不幸的是,有时,当我想要对其它数据进行排名时,CAD工具厂商所提供的常用排名算法并不适合。因此,能够扩展到处理成百上千个测试和覆盖点才是一个排名算法的本质。
 
输入

通常情况下,我不得不从其他CAD程序产生的文本或HTML文件来解析我的输入 - 这是个是单调乏味的工作,我会跳过这个乏味的工作,而通过以Python字典的形式提供理想的输入。 (有时用于解析输入文件的代码可以跟排名算法一样大或着更大)。
让我们假设每个ISG测试都有一个名称,在确定的“时间”内运行,当模拟显示'覆盖'设计中的 一组编号的特性时。解析之后,所收集的输入数据由程序中的结果字典来表示。

 

results = {
#  'TEST': ( TIME, set([COVERED_POINT ...])),
 'test_00': ( 2.08, set([2, 3, 5, 11, 12, 16, 19, 23, 25, 26, 29, 36, 38, 40])),
 'test_01': ( 58.04, set([0, 10, 13, 15, 17, 19, 20, 22, 27, 30, 31, 33, 34])),
 'test_02': ( 34.82, set([3, 4, 6, 12, 15, 21, 23, 25, 26, 33, 34, 40])),
 'test_03': ( 32.74, set([4, 5, 10, 16, 21, 22, 26, 39])),
 'test_04': (100.00, set([0, 1, 4, 6, 7, 8, 9, 11, 12, 18, 26, 27, 31, 36])),
 'test_05': ( 4.46, set([1, 2, 6, 11, 14, 16, 17, 21, 22, 23, 30, 31])),
 'test_06': ( 69.57, set([10, 11, 15, 17, 19, 22, 26, 27, 30, 32, 38])),
 'test_07': ( 85.71, set([0, 2, 4, 5, 9, 10, 14, 17, 24, 34, 36, 39])),
 'test_08': ( 5.73, set([0, 3, 8, 9, 13, 19, 23, 25, 28, 36, 38])),
 'test_09': ( 15.55, set([7, 15, 17, 25, 26, 30, 31, 33, 36, 38, 39])),
 'test_10': ( 12.05, set([0, 4, 13, 14, 15, 24, 31, 35, 39])),
 'test_11': ( 52.23, set([0, 3, 6, 10, 11, 13, 23, 34, 40])),
 'test_12': ( 26.79, set([0, 1, 4, 5, 7, 8, 10, 12, 13, 31, 32, 40])),
 'test_13': ( 16.07, set([2, 6, 9, 11, 13, 15, 17, 18, 34])),
 'test_14': ( 40.62, set([1, 2, 8, 15, 16, 19, 22, 26, 29, 31, 33, 34, 38])),
 }<span style="font-size:10pt;line-height:1.5;font-family:'sans serif', tahoma, verdana, helvetica;"></span>

 

贪婪排名算法的核心是对当前选择测试的子集进行排序:

  •     至少用一个测试集覆盖尽可能大的范围。
  •     经过第一个步骤,逐步减少测试集,同时覆盖尽可能大的范围。
  •     给选择的测试做出一个排序,这样小数据集的测试也可以选择使用
  •     完成上述排序后,接下来就可以优化算法的执行时间了
  •     当然,他需要能在很大的测试集下工作。

贪婪排名算法的工作原理就是先选择当前测试集的某一项的最优解,然后寻找下一项的最优解,依次进行...

如果有两个以上的算法得出相同的执行结果,那么将以执行”时间“来比较两种算法优劣。

用下面的函数完成的算法:
 

def greedyranker(results):
  results = results.copy()
  ranked, coveredsofar, costsofar, round = [], set(), 0, 0
  noncontributing = []
  while results:
    round += 1
    # What each test can contribute to the pool of what is covered so far
    contributions = [(len(cover - coveredsofar), -cost, test)
             for test, (cost, cover) in sorted(results.items()) ]
    # Greedy ranking by taking the next greatest contributor        
    delta_cover, benefit, test = max( contributions )
    if delta_cover > 0:
      ranked.append((test, delta_cover))
      cost, cover = results.pop(test)
      coveredsofar.update(cover)
      costsofar += cost
    for delta_cover, benefit, test in contributions:
      if delta_cover == 0:
        # this test cannot contribute anything
        noncontributing.append( (test, round) )
        results.pop(test)
  return coveredsofar, ranked, costsofar, noncontributing

每次while循环(第5行),下一个最好的测试会被追加到排名和测试,不会 丢弃贡献的任何额外覆盖(37-41行)

上面的函数是略显简单,所以我花了一点时间用tutor来标注,当运行时打印出它做的。
函数(有指导):
它完成同样的事情,但代码量更大,太繁冗:
 

def greedyranker(results, tutor=True):
  results = results.copy()
  ranked, coveredsofar, costsofar, round = [], set(), 0, 0
  noncontributing = []
  while results:
    round += 1
    # What each test can contribute to the pool of what is covered so far
    contributions = [(len(cover - coveredsofar), -cost, test)
             for test, (cost, cover) in sorted(results.items()) ]
    if tutor:
      print('\n## Round %i' % round)
      print(' Covered so far: %2i points: ' % len(coveredsofar))
      print(' Ranked so far: ' + repr([t for t, d in ranked]))
      print(' What the remaining tests can contribute, largest contributors first:')
      print('  # DELTA, BENEFIT, TEST')
      deltas = sorted(contributions, reverse=True)
      for delta_cover, benefit, test in deltas:
        print('   %2i,  %7.2f,  %s' % (delta_cover, benefit, test))
      if len(deltas)>=2 and deltas[0][0] == deltas[1][0]:
        print(' Note: This time around, more than one test gives the same')
        print('    maximum delta contribution of %i to the coverage so far'
            % deltas[0][0])
        if deltas[0][1] != deltas[1][1]:
          print('    we order based on the next field of minimum cost')
          print('    (equivalent to maximum negative cost).')
        else:
          print('    the next field of minimum cost is the same so')
          print('    we arbitrarily order by test name.')
      zeroes = [test for delta_cover, benefit, test in deltas
           if delta_cover == 0]
      if zeroes:
        print(' The following test(s) cannot contribute more to coverage')
        print(' and will be dropped:')
        print('  ' + ', '.join(zeroes))
 
    # Greedy ranking by taking the next greatest contributor        
    delta_cover, benefit, test = max( contributions )
    if delta_cover > 0:
      ranked.append((test, delta_cover))
      cost, cover = results.pop(test)
      if tutor:
        print(' Ranking %s in round %2i giving extra coverage of: %r'
            % (test, round, sorted(cover - coveredsofar)))
      coveredsofar.update(cover)
      costsofar += cost
 
    for delta_cover, benefit, test in contributions:
      if delta_cover == 0:
        # this test cannot contribute anything
        noncontributing.append( (test, round) )
        results.pop(test)
  if tutor:
    print('\n## ALL TESTS NOW RANKED OR DISCARDED\n')
  return coveredsofar, ranked, costsofar, noncontributing

每一块以  if tutor开始:  添加以上代码

样值输出
调用排序并打印结果的代码是:
 

totalcoverage, ranking, totalcost, nonranked = greedyranker(results)
print('''
A total of %i points were covered,
using only %i of the initial %i tests,
and should take %g time units to run.
 
The tests in order of coverage added:
   
  TEST DELTA-COVERAGE'''
 % (len(totalcoverage), len(ranking), len(results), totalcost))
print('\n'.join(' %6s %i' % r for r in ranking))

结果包含大量东西,来自tutor并且最后跟着结果。

对这个伪随机生成15条测试数据的测试案例,看起来只需要七条去产生最大的总覆盖率。(而且如果你愿意放弃三条测试,其中每个只覆盖了一个额外的点,那么15条测试中的4条就将给出92.5%的最大可能覆盖率)。

Python 相关文章推荐
python实现根据主机名字获得所有ip地址的方法
Jun 28 Python
浅谈pyhton学习中出现的各种问题(新手必看)
May 17 Python
Python遍历pandas数据方法总结
Feb 09 Python
python简单商城购物车实例代码
Mar 15 Python
Python实现求解一元二次方程的方法示例
Jun 20 Python
python 制作自定义包并安装到系统目录的方法
Oct 27 Python
微信小程序python用户认证的实现
Jul 29 Python
Python爬虫库BeautifulSoup的介绍与简单使用实例
Jan 25 Python
python对文件的操作方法汇总
Feb 28 Python
如何将Pycharm中调整字体大小的方式设置为&quot;ctrl+鼠标滚轮上下滑&quot;
Nov 17 Python
pandas实现导出数据的四种方式
Dec 13 Python
python编写扎金花小程序的实例代码
Feb 23 Python
在Linux下调试Python代码的各种方法
Apr 17 #Python
Python脚本在Appium库上对移动应用实现自动化测试
Apr 17 #Python
Python中生成器和yield语句的用法详解
Apr 17 #Python
使用Python脚本在Linux下实现部分Bash Shell的教程
Apr 17 #Python
使用Python的Scrapy框架编写web爬虫的简单示例
Apr 17 #Python
用Python的Django框架编写从Google Adsense中获得报表的应用
Apr 17 #Python
在Docker上开始部署Python应用的教程
Apr 17 #Python
You might like
php数据库连接时容易出错的特殊符号问题
2010/09/01 PHP
PHP中break及continue两个流程控制指令区别分析
2011/04/18 PHP
PHP curl使用实例
2015/07/02 PHP
让getElementsByName适应IE和firefox的方法
2007/09/24 Javascript
JavaScript高级程序设计 阅读笔记(四) ECMAScript中的类型转换
2012/02/27 Javascript
js实现防止被iframe的方法
2015/07/03 Javascript
AngularJS教程之MVC体系结构详解
2016/08/16 Javascript
jQuery设计思想
2017/03/07 Javascript
基于vue2.0+vuex的日期选择组件功能实现
2017/03/13 Javascript
微信小程序 动态传参实例详解
2017/04/27 Javascript
详解Vue用自定义指令完成一个下拉菜单(select组件)
2017/10/31 Javascript
小程序组件之仿微信通讯录的实现代码
2018/09/12 Javascript
Vant的安装和配合引入Vue.js项目里的方法步骤
2018/12/05 Javascript
fetch 如何实现请求数据
2018/12/20 Javascript
浅谈js闭包理解
2019/04/01 Javascript
关于JS解构的5种有趣用法
2019/09/05 Javascript
Vue 实现输入框新增搜索历史记录功能
2019/10/15 Javascript
js实现无缝轮播图
2020/03/09 Javascript
部署vue+Springboot前后端分离项目的步骤实现
2020/05/31 Javascript
JavaScript实现页面高亮操作提示和蒙板
2021/01/04 Javascript
用python登录Dr.com思路以及代码分享
2014/06/25 Python
Python实现基于HTTP文件传输实例
2014/11/08 Python
python smtplib模块发送SSL/TLS安全邮件实例
2015/04/08 Python
python生成二维码的实例详解
2017/10/29 Python
树莓派使用python-librtmp实现rtmp推流h264的方法
2019/07/22 Python
win10下安装Anaconda的教程(python环境+jupyter_notebook)
2019/10/23 Python
Python 矩阵转置的几种方法小结
2019/12/02 Python
Otticanet美国:最顶尖的世界名牌眼镜, 能得到打折季的价格
2019/03/10 全球购物
城市轨道交通工程职业生涯规划书范文
2014/09/16 职场文书
四风个人对照检查材料思想汇报
2014/09/25 职场文书
2014年仓库管理员工作总结
2014/11/18 职场文书
行政经理岗位职责
2015/04/15 职场文书
女性健康知识讲座通知
2015/04/23 职场文书
绿色环保倡议书
2015/04/28 职场文书
VUE使用draggable实现组件拖拽
2022/04/06 Vue.js
python热力图实现的完整实例
2022/06/25 Python