京公网安备 11010802034615号
经营许可证编号:京B2-20210330
在Python中实现贪婪排名算法的教程
这篇文章主要介绍了在Python中实现贪婪排名算法的教程,也是对学习算法的一个很好的演示,需要的朋友可以参考下
在较早的一遍文章中,我曾经提到过我已经写了一个属于自己的排序算法,并且认为需要通过一些代码来重新回顾一下这个排序算法。
对于我所完成的工作,我核实并且保证微处理器的安全。对非常复杂的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%的最大可能覆盖率)。
数据分析咨询请扫描二维码
若不方便扫码,搜微信号:CDAshujufenxi
在 MySQL 实际应用中,“频繁写入同一表” 是常见场景 —— 如实时日志存储(用户操作日志、系统运行日志)、高频交易记录(支付 ...
2025-10-30为帮助教育工作者、研究者科学分析 “班级规模” 与 “平均成绩” 的关联关系,我将从相关系数的核心定义与类型切入,详解 “数 ...
2025-10-30对 CDA(Certified Data Analyst)数据分析师而言,“相关系数” 不是简单的数字计算,而是 “从业务问题出发,量化变量间关联强 ...
2025-10-30在构建前向神经网络(Feedforward Neural Network,简称 FNN)时,“隐藏层数目设多少?每个隐藏层该放多少个神经元?” 是每个 ...
2025-10-29这个问题切中了 Excel 用户的常见困惑 —— 将 “数据可视化工具” 与 “数据挖掘算法” 的功能边界混淆。核心结论是:Excel 透 ...
2025-10-29在 CDA(Certified Data Analyst)数据分析师的工作中,“多组数据差异验证” 是高频需求 —— 例如 “3 家门店的销售额是否有显 ...
2025-10-29在数据分析中,“正态分布” 是许多统计方法(如 t 检验、方差分析、线性回归)的核心假设 —— 数据符合正态分布时,统计检验的 ...
2025-10-28箱线图(Box Plot)作为展示数据分布的核心统计图表,能直观呈现数据的中位数、四分位数、离散程度与异常值,是质量控制、实验分 ...
2025-10-28在 CDA(Certified Data Analyst)数据分析师的工作中,“分类变量关联分析” 是高频需求 —— 例如 “用户性别是否影响支付方式 ...
2025-10-28在数据可视化领域,单一图表往往难以承载多维度信息 —— 力导向图擅长展现节点间的关联结构与空间分布,却无法直观呈现 “流量 ...
2025-10-27这个问题问到了 Tableau 中两个核心行级函数的经典组合,理解它能帮你快速实现 “相对位置占比” 的分析需求。“index ()/size ( ...
2025-10-27对 CDA(Certified Data Analyst)数据分析师而言,“假设检验” 绝非 “套用统计公式的机械操作”,而是 “将模糊的业务猜想转 ...
2025-10-27在数字化运营中,“凭感觉做决策” 早已成为过去式 —— 运营指标作为业务增长的 “晴雨表” 与 “导航仪”,直接决定了运营动作 ...
2025-10-24在卷积神经网络(CNN)的训练中,“卷积层(Conv)后是否添加归一化(如 BN、LN)和激活函数(如 ReLU、GELU)” 是每个开发者都 ...
2025-10-24在数据决策链条中,“统计分析” 是挖掘数据规律的核心,“可视化” 是呈现规律的桥梁 ——CDA(Certified Data Analyst)数据分 ...
2025-10-24在 “神经网络与卡尔曼滤波融合” 的理论基础上,Python 凭借其丰富的科学计算库(NumPy、FilterPy)、深度学习框架(PyTorch、T ...
2025-10-23在工业控制、自动驾驶、机器人导航、气象预测等领域,“状态估计” 是核心任务 —— 即从含噪声的观测数据中,精准推断系统的真 ...
2025-10-23在数据分析全流程中,“数据清洗” 恰似烹饪前的食材处理:若食材(数据)腐烂变质、混杂异物(脏数据),即便拥有精湛的烹饪技 ...
2025-10-23在人工智能领域,“大模型” 已成为近年来的热点标签:从参数超 1750 亿的 GPT-3,到万亿级参数的 PaLM,再到多模态大模型 GPT-4 ...
2025-10-22在 MySQL 数据库的日常运维与开发中,“更新数据是否会影响读数据” 是一个高频疑问。这个问题的答案并非简单的 “是” 或 “否 ...
2025-10-22