`
tiantian911
  • 浏览: 224872 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Picece選擇算法

阅读更多
晚飯前后用了點時間把piece picker的模塊代碼看完,很順利。

from random import randrange, shuffle, choice


class PiecePicker(object):

    def __init__(self, numpieces, config):
        self.config = config # config 的 list, dict 嵌套结构
        self.numpieces = numpieces #片数?
        self.interests = [range(numpieces)] #interest是一个list,表示第i位的piece收到i个have,例如[[0,3],1,2]表示0和3两片没收到have,1的片收到一个have,2的片收到2个have,初始化为 [[0,1,2,3...piecenum]]
        self.pos_in_interests = range(numpieces) #第 i 位的数字表示片段 i 是 interest 数组中的相应的list中的位置。 通过这种方式在list中表示顺序。
        self.numinterests = [0] * numpieces #list第i位收到have的个数.   例如:[2,3,5,2] 表示第0,1,2,3片分别有2,3,5,2个have , 初始化应该为[0,0,0,0...]
        self.have = [False] * numpieces #每一片的自身下载情况, 初始是 [false,false,false.......]
        self.crosscount = [numpieces]
        self.started = []
        self.seedstarted = []
        self.numgot = 0 #我收到的piece个数
        self.scrambled = range(numpieces)
        shuffle(self.scrambled)

    def got_have(self, piece):
        numint = self.numinterests[piece] #已经有几个have了?
        self.crosscount[numint + self.have[piece]] -= 1
        self.numinterests[piece] += 1
        try:
            self.crosscount[numint + 1 + self.have[piece]] += 1
        except IndexError:
            self.crosscount.append(1)
        if self.have[piece]:
            return
        if numint == len(self.interests) - 1:
            self.interests.append([])
        self._shift_over(piece, self.interests[numint], self.interests[numint + 1])

    def lost_have(self, piece):
        numint = self.numinterests[piece]
        self.crosscount[numint + self.have[piece]] -= 1
        self.numinterests[piece] -= 1
        self.crosscount[numint - 1 + self.have[piece]] += 1
        if self.have[piece]:
            return
        self._shift_over(piece, self.interests[numint], self.interests[numint - 1])

    def _shift_over(self, piece, l1, l2): #调整3个数组参数
        p = self.pos_in_interests[piece]
        l1[p] = l1[-1]
        self.pos_in_interests[l1[-1]] = p
        del l1[-1]
        newp = randrange(len(l2) + 1)
        if newp == len(l2):
            self.pos_in_interests[piece] = len(l2)
            l2.append(piece)
        else:
            old = l2[newp]
            self.pos_in_interests[old] = len(l2)
            l2.append(old)
            l2[newp] = piece
            self.pos_in_interests[piece] = newp

    def requested(self, piece, seed = False): #request某个片段
        if piece not in self.started:
            self.started.append(piece)
        if seed and piece not in self.seedstarted:
            self.seedstarted.append(piece)

    def complete(self, piece): #完成了某个片段
        assert not self.have[piece]
        self.have[piece] = True #改have
        self.crosscount[self.numinterests[piece]] -= 1 # numinterest[piece] 是 piece 有 have 的个数
        try:
            self.crosscount[self.numinterests[piece] + 1] += 1
        except IndexError:
            self.crosscount.append(1)
        self.numgot += 1
        l = self.interests[self.numinterests[piece]] # 跟 piece 有一样 have 的片的 list
        p = self.pos_in_interests[piece] # piece 在 同样 have 的 list 中的次序 
        l[p] = l[-1] #l[p] 就是 piece , l[-1] 为最后一个
        self.pos_in_interests[l[-1]] = p # 把 p 交换到l 的最后一位, 在 pos_in_interest 中交换
        del l[-1]
        #以上的几行的作用综合起来就是:完成了某个片段之后,把该 piece 在 pos_in_interest 中把它移动到最后一位
        #但是,已经 download 完成的 piece , 为什么不在 interest 中把它删掉?
        try:
            self.started.remove(piece)
            self.seedstarted.remove(piece)
        except ValueError:
            pass

    def next(self, havefunc, seed = False): # 关键的方法, 如何选择下一个下载的piece
        bests = None
        bestnum = 2 ** 30 # 上限?
        if seed:
            s = self.seedstarted
        else:
            s = self.started
        for i in s:
            if havefunc(i): #i 片有 have
                if self.numinterests[i] < bestnum:
                    bests = [i]
                    bestnum = self.numinterests[i]
                elif self.numinterests[i] == bestnum:
                    bests.append(i)
        if bests: # 如果不为空
            return choice(bests) # choice 方法从 list中随机选择一个返回。
        if self.numgot < self.config['rarest_first_cutoff']: #rareest_first_cutoff 默认为1 , 如果一个片也没有got, 就random_first
            for i in self.scrambled:
                if havefunc(i):
                    return i
            return None
        for i in xrange(1, min(bestnum, len(self.interests))): #xrange 这个方法比较奇妙,会返回一个xrange型的对象
          #a = xrange(0,100)   print type(a)   print a  print a[0], a[1] 会输出 <type 'xrange'>  xrange(100)  0 1
          # 对 interest 从1 开始遍历:为什么是1? 0的不能选,因为没有have, 从1遍历,找到就跳出
          #这样可以保证rarest first,因为这里的i代表着有have的个数,从最少开始找自然的就能满足这条规则。
            for j in self.interests[i]:
                if havefunc(j):
                    return j
        return None # 这些手段都找不到最终需要的piece,返回空

    def am_I_complete(self):
        return self.numgot == self.numpieces

    def bump(self, piece):
        l = self.interests[self.numinterests[piece]] # 跟 piece 有一样 have 的片的 list
        pos = self.pos_in_interests[piece]  # piece 在 同样 have 的 list 中的次序 
        del l[pos]
        l.append(piece)
        for i in range(pos,len(l)):
            self.pos_in_interests[l[i]] = i # 修正pos
        try:
            self.started.remove(piece)
            self.seedstarted.remove(piece)
        except ValueError:
            pass
分享到:
评论

相关推荐

    P2P视频直播数据调度算法

    其中,Rarest First策略是一种常用的Piece选择算法,其基本原则是在所有邻居中选择拥有最少的Piece的节点进行下载,以确保整个网络中数据的均匀分布。 ##### 1.2 节点能力的概念 为了更好地理解P2P视频直播系统中...

    软件开发-下载软件设计论文

    【软件开发-下载软件设计论文】这篇论文主要...通过对piece和peer选择算法的分析,读者可以理解BitTorrent如何实现高效的数据共享,这对于软件开发人员尤其是从事P2P或文件分发系统设计的人来说,具有很高的学习价值。

    piecetable.zip

    《piecetable 数据结构的C语言实现详解》 在计算机科学中,数据结构是存储和组织...通过深入学习和理解这两个源代码文件,我们可以提升对C语言数据结构和算法的理解,这对于任何IT专业人员来说都是非常宝贵的技能。

    NLP-Subword三大算法原理:BPE、WordPiece、ULM.pdf

    本篇文章将深入探讨三种主流的Subword算法:Byte Pair Encoding(BPE)、WordPiece和Unigram Language Model(ULM)。 首先,让我们来看看Byte Pair Encoding(BPE)。BPE是一种数据压缩技术,最初用于文本压缩,...

    NLP-Subword三大算法原理:BPE、WordPiece、ULM.rar

    其次,WordPiece算法由Google提出,与BPE类似,也是用于构建词汇表的子词模型。不同之处在于,WordPiece的目标是最大化句子中每个单词的概率,而不是寻找最常见的字符对。它通过最小化分割后的单词数量来实现这一点...

    页面淘汰算法演示系统 操作系统课程设计

    3. **最佳替换算法(OPT, Optimal Page Replacement)**:理论上最优的算法,总是选择未来最长时间内不再被引用的页面淘汰。然而,由于无法预知未来,实际操作中难以实现。 4. **第二次机会(Second Chance)**:...

    Python库 | sentencepiece-0.1.96-cp37-cp37m-win_amd64.whl

    2. **BPE(Byte Pair Encoding)算法**:SentencePiece实现了BPE,这是一种基于字符级别的联合学习方法,通过合并频繁出现的字符对来逐步构建词汇表,有效地处理未知词汇和词汇表大小的控制。 3. **Unigram模型**:...

    Java俄罗斯方块 算法思路

    ### Java俄罗斯方块算法设计与实现 在斯坦福大学CS108课程的第14份讲义中,由Nick Parlante设计的作业——“Java俄罗斯方块算法思路”(HW2Tetris),旨在通过模块化面向对象编程(OOP)的方法构建一套俄罗斯方块...

    显示连接文件建立算法 操作系统实验

    从给定的文件标题、描述、标签以及部分内容中,我们可以提炼出有关操作系统的显示连接文件建立算法的关键知识点。这段信息主要涉及的是操作系统中文件管理的一部分,特别是文件控制块(File Control Block, FCB)和...

    用于非监督中文分词算法的中文分词词库

    在这个场景中,我们关注的是一个专门用于非监督中文分词算法的词库,该词库包含了大约20万个词汇。这样的词库在构建和训练非监督模型时起着至关重要的作用,因为它可以提供大量的先验知识,帮助算法理解中文文本的...

    sudoku-solver:使用DLX算法的快速数独难题求解器:puzzle_piece:

    算法通过选择合适的列进行删除和恢复,以模拟回溯过程,有效地减少了搜索空间。这种设计使得DLX在解决数独这类问题时具有较高的效率。 在这个“sudoku-solver”项目中,源代码可能包括以下几个部分: 1. 数独谜题的...

    操作系统课程设计——CPU时间片轮转算法.doc

    操作系统课程设计中,CPU时间片轮转算法是一种用于模拟处理机调度的重要方法,它主要目的是理解和实践进程管理的核心功能。时间片轮转法基于先来先服务(FCFS)原则,但增加了时间片的概念,以确保系统能在指定时间...

    有限缓冲区流水车间调度的混合人工蜂群算法

    5. 在HABC算法中,初始种群的初始化采用了一个启发式算法WPFE(Work Piece Flow Estimation)。这个方法能够提升初始种群的质量,进而增加算法在搜索过程中的效率。 6. 研究者设计了基于六种不同结构的混合调度算法...

    人工智能-大模型-基于大模型ChatGLM,微调方式为LORA,集SFT、RM、PPO算法为一体项目

    基于大模型ChatGLM,微调方式为LORA,集SFT、RM、PPO算法为一体项目 要求 Python 3.8+ 和 PyTorch 1.13.1 Transformers、Datasets、Accelerate、PEFT 和 TRL protobuf、cpm_kernels 和 sentencepiece jieba、rouge_...

    SM4国密算法加解密 代码详解

    SM4国密算法加解密 代码加详解

    人工智能大作业-基于ALBERT+机器学习算法实现文本分类python源码+项目说明+文本数据集.zip

    ALBERT通过使用SentencePiece进行词汇表示,实现了句子级别的交互,增强了模型的语义理解能力。 2. 机器学习算法:在这个项目中,ALBERT可能被用作特征提取器,提取文本的高维表示,然后这些表示会被输入到传统的...

    C++编写五子棋(带AI,mfc,附教程)

    C++是一种广泛应用的面向对象的编程语言,其强大的性能和灵活性使得它成为开发游戏和复杂应用的理想选择。 1. **C++基础**: - C++是一种静态类型的、编译式的、通用的、大小写敏感的、不仅支持过程化编程,也支持...

Global site tag (gtag.js) - Google Analytics