2016-05-16 53 views
3

你有多冷,加快下面的代码能够做100多个人?随机的沃克码python

""" Random Walker """ 
import numpy as np 
import scipy as sp 
import random as rd 
import time 

def procedure(): 
    time.sleep(2.5) 
    t0C = time.clock() 
    t0 = time.time() 

    """Definitions""" 

    def ifilterfalse(predicate, iterable): 
     # ifilterfalse(lambda x: x%2, range(10)) --> 0 2 4 6 8 
     if predicate is None: 
      predicate = bool 
     for x in iterable: 
      if not predicate(x): 
       yield x 

    def unique_everseen(iterable, key=None): 
     "List unique elements, preserving order. Remember all elements ever seen." 
     # unique_everseen('AAAABBBCCDAABBB') --> A B C D 
     # unique_everseen('ABBCcAD', str.lower) --> A B C D 
     seen = set() 
     seen_add = seen.add 
     if key is None: 
      for element in ifilterfalse(seen.__contains__, iterable): 
       seen_add(element) 
       yield element 
     else: 
      for element in iterable: 
       k = key(element) 
       if k not in seen: 
        seen_add(k) 
        yield element 

    """Creating the Random Walk""" 

    n=int(input('Number of Individuals at Table: ')) 
    iters=10000 
    final=np.zeros(n) 
    total=0 
    for j in xrange(iters): 
     d=np.array([0]) 
     i=0 
     while i<1: 
      new=d[len(d)-1]+rd.choice([-1,1]) 
      if new<0: 
       new+=n 
      elif new>=n: 
       new-=n 
      d=np.append(d,new) 
      dshort=list(unique_everseen(d)) 
      if len(dshort)>=n: 
       i=1 
      last=dshort[len(dshort)-1] 
      length=len(d) 
     final[last]+=1 
     total+=length 

    final=np.round(final/iters,4) 
    total=round(total/iters,3) 

    """Writing To A File""" 

    print (40 * '-') 
    print (" ") 
    print (" Percentages: ") 
    print (" ") 
    print (" S#:"+"  S#:".join(map(str,range(n)))) 
    print (" "+"% ".join(map(str,final))+"%") 
    print (" ") 
    print (" Average Number of Passes of Plate: {}".format(total)) 
    print (" ") 
    print (40 * '-') 

    # measure process time 
    print time.clock() - t0C, "seconds process time" 

    # measure wall time 
    print time.time() - t0, "seconds wall time" 


if __name__ == "__main__": 
    procedure() 

现在对10个人的情况下,时间:

5.877529秒过程时间

12.9134569168秒壁时间

的问题是,当个体的数目(100 ,1000)增加代码太慢,有什么建议?

+0

这将是更容易,如果您修复缩进 – Jivan

+0

对此深感抱歉地回答,压痕已固定。 – user3671704

回答

2

问题是unique_everseen在连续执行中做了几乎相同的工作,耗费了太多时间。这里是一个简化版本,去掉unique_everseen功能和d列表,并直接使用seen组在主回路和last VAR保持的最后一项:

""" Random Walker """ 
import random as rd 
import time 

def procedure(): 
    n = int(input('Number of Individuals at Table: ')) 

    t0C = time.clock() 
    t0 = time.time() 

    iters = 10000 
    final = [0] * n 
    total = 0 
    for j in xrange(iters): 
     last = 0 
     count = 1 
     seen = set([0]) 
     while len(seen) < n: 
      count += 1; 
      new = last + rd.choice([-1, 1]) 
      if new < 0: 
       new += n 
      elif new >= n: 
       new -= n 
      seen.add(new) 
      last = new 
     final[last] += 1 
     total += count 

    final = [round(float(f)/iters, 4) for f in final] 
    total = round(float(total)/iters, 3) 

    """Writing To A File""" 

    print(40 * '-') 
    print(" ") 
    print(" Percentages: ") 
    print(" ") 
    print(" S#:" + "  S#:".join(map(str, range(n)))) 
    print(" " + "% ".join(map(str, final)) + "%") 
    print(" ") 
    print(" Average Number of Passes of Plate: {}".format(total)) 
    print(" ") 
    print(40 * '-') 

    # measure process time 
    print time.clock() - t0C, "seconds process time" 

    # measure wall time 
    print time.time() - t0, "seconds wall time" 


if __name__ == "__main__": 
    procedure() 

注意去除numpy依赖允许脚本运行pypy

一些结果(secods)

  • 10个人
    • 蟒:0.472
    • pypy:0.084
  • 为100个个体
    • 蟒:49.352
    • pypy:3.256
  • 500个人
    • pypy:80.460
  • 1000个人
    • pypy:318.392
+0

是的,虽然我注意到总数的精度/结果改变超过1个单位,但速度更快? – user3671704

+1

区别的一个原因是,我用total = round(float(total)/ iters,3)替换了'total = round(total/iters,3)',以使分区(和循环)正常工作('total/iters'是一个整数部分)。还忘了用'[0]'初始化'seen',现在我修好了。 – malbarbo