varying degree of shuffling using random module python

I am using two architecture programs, with visual programming plugins (Grasshopper for Rhino and Dynamo for Revit – for those that know / are interested)

Grasshopper contains a function called ‘Jitter’ this will shuffle a list, however it has an input from 0.0 to 1.0 which controls the degree of shuffling – 0.0 results in no shuffling 1.0 produces a complete shuffle.

The second of the programs (Dynamo) does not contain this functionality. It contains a shuffle module (which contains a seed value) however it is a complete random shuffle.

Ultimately the goal is to produce a series of solid and glazed panels, but to produce a slight random effect (but avoiding large clumping of solid and glazed elements – hence I want a “light shuffle”)

I have written a code which will calculate the number of glazed(True) and solid(False) values required and then evenly distribute True and False values based on the number of items and percent specified.

I have checked out the random module reference however I’m not familiar with the various distributions as described.

Could someone help out or point me in the right direction if an existing function would achieve this.

(I have cheated slightly by adding True False alternately to make up the correct number of items within the list – list3 is the final list, list2 contains the repeated module of true falses)

Many thanks

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))

Answer

Here is an approach based on this paper which proves a result about the mixing time needed to scramble a list by using swaps of adjacent items

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

A test, each line showing the result of jitter with various percents being applied to the same list:

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

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

Typical output:

00000000000000000000111111111111111111110000000000000000000011111111111111111111
00000000000000111100001101111011011111001010000100010001101000110110111111111111
00000000100100000101111110000110111101000001110001101001010101100011111111111110
00000001010010011011000100111010101100001111011100100000111010110111011001011111
00100001100000001101010000011010011011111011001100000111011011111011010101011101
00000000011101000110000110000010011001010110011111100100111101111011101100111110
00110000000001011001000010110011111101001111001001100101010011010111111011101100
01101100000100100110000011011000001101111111010100000100000110111011110011011111
01100010110100010100010100011000000001000101100011111011111011111011010100011111
10011100101000100010001100100000100111001111011011000100101101101010101101011111
10000000001000111101101011000011010010110011010101110011010100101101011110101110

I’m not sure how principled the above is, but it seems like a reasonable place to start.

Leave a Reply

Your email address will not be published. Required fields are marked *