2017-01-31 111 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