2017-01-31 10 views
4

Я использую две программы архитектуры, с визуальными плагинами программирования (Кузнечик для Rhino и Динамо для Revit - для тех, кто знает/заинтересованы)различной степени перетасовки с использованием случайных модуль питона

Кузнечик содержит функцию под названием «Дрожание 'это будет перетасовывать список, однако он имеет вход от 0.0 до 1.0, который контролирует степень перетасовки - 0.0 приводит к отсутствию перетасовки 1.0, что приводит к полной перетасовке.

Вторая из программ (Dynamo) не содержит этой функции. Он содержит модуль перетасовки (который содержит начальное значение), но это полная случайная перетасовка.

В конечном счете, цель состоит в том, чтобы произвести серию твердых и застекленных панелей, но для получения небольшого случайного эффекта (но избегая большие комков твердых и стекловидных элементов - следовательно, я хочу «легкую перетасовать»)

I написали код, который рассчитает количество требуемых застекленных (истинных) и твердых (False) значений, а затем равномерно распределит значения True и False в зависимости от количества указанных элементов и процентов.

Я проверил случайную ссылку модуля, но я не знаком с различными дистрибутивами, как описано.

Может кто-нибудь помочь или указать мне в правильном направлении, если существующая функция достигнет этого.

(я немного обманутыми, добавив True False поочередно, чтобы составить правильное количество элементов в списке - песни3 итоговый список, песни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», поэтому реализация полного тасования в качестве образца бессмысленна. Что касается «дрожания» - возможно, случайные свопы элементов со своими соседями определенное количество раз, что приведет к диффузии исходного порядка. –

ответ

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 под капотом.

O (n) shuffle начинается с первого элемента массива и свопирует его со случайным высшим элементом, затем заменяет второй элемент случайным высшим элементом и так далее.

Естественно, остановка этой перетасовки, прежде чем вы достигнете последнего элемента с некоторой долей [0,1], даст частично рандомизированный массив, как вы хотите.

К сожалению, эффект от вышеизложенного заключается в том, что вся «случайность» создается на одной стороне массива.

Поэтому сделайте список индексов массива, перетасуйте их полностью, а затем используйте индексы в качестве входа в алгоритм Fisher-Yates, чтобы частично отсортировать исходный массив.

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