2017-01-31 79 views
4

不同洗牌的程度,我用两个建筑方案,可视化编程插件(蚂蚱犀牛和迪纳摩的Revit中 - 对于那些知道/有兴趣)使用随机模块蟒蛇

蝈蝈包含一个名为“抖动功能'这将洗刷一个列表,但是它有一个从0.0到1.0的输入来控制洗牌的程度--0.0导致没有洗牌1.0会产生一个完整的洗牌。

第二个程序(Dynamo)不包含此功能。它包含一个shuffle模块(它包含一个种子值),但它是一个完整的随机洗牌。

最终的目标是要生产出一系列固体和玻璃面板的,但以产生轻微的随机效应(但避免大结块固体和釉面元件 - 因此我想“光洗牌”)

我已经编写了一个代码,用于计算所需的玻璃(真)值和实值(假)值的数量,然后根据项目数量和指定的百分比均匀分配True和False值。

我已经签出了随机模块参考,但我不熟悉所述的各种分布。

如果现有的功能可以实现这一点,有人可以帮助或指出我的方向是正确的。

(我已经加入对错交替,以弥补列表中的项目的正确数量略有被骗 - 项目list3是最终名单,列表2包含真正falses的重复模块)

非常感谢

import math 
import random 

percent = 30 
items = 42 

def remainder(): 
    remain = items % len(list2) 

    list3.append(True) 
    remain -= 1 

    while remain > 0 : 
     list3.append(False) 
     remain -= 1 

    return list3 

#find module of repeating True and False values 
list1 = ([True] + [False] * int((100/percent)-1)) 

#multiply this list to nearest multiple based on len(items) 
list2 = list1 * int(items/(100/percent)) 

# make a copy of list2 
list3 = list2[:] 

#add alternating true and false to match len(list3) to len(items) 
remainder() 

#an example of a completely shuffled list - which is not desired 
shuffled = random.sample(list3, k = len(list3)) 
+1

Python的随机模块有一个'shuffle'方法,所以实现一个完整的shuffle作为一个样本是毫无意义的。就“抖动”而言 - 或许与其邻居进行随机交换一定次数,这将导致原始顺序扩散。 –

回答

2

这里是基于this paper的方法,其证明了一个有关通过使用相邻的项目

from random import choice 
from math import log 

def jitter(items,percent): 
    n = len(items) 
    m = (n**2 * log(n)) 
    items = items[:] 
    indices = list(range(n-1)) 
    for i in range(int(percent*m)): 
     j = choice(indices) 
     items[j],items[j+1] = items[j+1],items[j] 
    return items 

测试的互换来加扰的列表所需要的混合时间结果,每个线表示jitter其结果各种百分比被施加到相同的列表:

ls = list(('0'*20 + '1'*20)*2) 

for i in range(11): 
    p = i/10.0 
    print(''.join(jitter(ls,p))) 

典型输出:

00000000000000000000111111111111111111110000000000000000000011111111111111111111 
00000000000000111100001101111011011111001010000100010001101000110110111111111111 
00000000100100000101111110000110111101000001110001101001010101100011111111111110 
00000001010010011011000100111010101100001111011100100000111010110111011001011111 
00100001100000001101010000011010011011111011001100000111011011111011010101011101 
00000000011101000110000110000010011001010110011111100100111101111011101100111110 
00110000000001011001000010110011111101001111001001100101010011010111111011101100 
01101100000100100110000011011000001101111111010100000100000110111011110011011111 
01100010110100010100010100011000000001000101100011111011111011111011010100011111 
10011100101000100010001100100000100111001111011011000100101101101010101101011111 
10000000001000111101101011000011010010110011010101110011010100101101011110101110 

我不知道以上是如何的原则,但它似乎是一个合理的开始。

+0

为什么省略'/(2 * pi ** 2)'? – Eric

+0

这是一个比我的更好的抖动定义 – Eric

+0

@Eric我第一次使用该术语的功能,但认为它对我来说看起来不够随意(不是我运行任何统计测试)。我认为最好在谨慎的方面犯错,以便“百分比= 1”产生完全争夺。 –

1

你指的其他算法可能是在引擎盖下使用Fisher-Yates shuffle。

This O(n) shuffle从数组的第一个元素开始,用随机更高元素交换,然后用随机更高元素交换第二个元素,依此类推。

当然,停止该洗牌,你在某个分数到达最后一个元素之前[0,1]将给予部分随机排列,就像你想要的。

不幸的是,上述的影响是所有的“随机性”都建立在数组的一侧。

因此,使数组索引的列表,完全洗牌这些,然后使用索引作为输入到费 - 耶茨算法以部分地排序原始数组。

2

有什么“度洗牌”(d)是指没有明确的定义,所以你需要选择一个。一种选择是:“剩余项目的部分未被洗牌(1-d)”。

您可以实现,作为:

  1. 生产指数列表
  2. 删除(1-d)* N其中
  3. 洗牌其余
  4. 重新插入那些去除
  5. 用这些查找原始数据中的数值

def partial_shuffle(x, d): 
    """ 
    x: data to shuffle 
    d: fraction of data to leave unshuffled 
    """ 
    n = len(x) 
    dn = int(d*n) 
    indices = list(range(n)) 
    random.shuffle(indices) 
    ind_fixed, ind_shuff = indices[dn:], indices[:dn] 

    # copy across the fixed values 
    result = x[:] 

    # shuffle the shuffled values 
    for src, dest in zip(ind_shuff, sorted(ind_shuff)): 
     result[dest] = x[src] 

    return result