0

I have a fairly big loop that needs to run 500 times, and I'm new to using the programming language and doing this type of simulation.

But I need to document the results of each run, and if the list (table1) contains either all 0's, all 1's or a mix of both.

I was just wondering what method would be the fastest to find out what proportion of the 500 simulations, resulted in a list that contained all 0's, all 1's or a mix and if append would slow it down too much.

for x in range(0, 500):

    times = 300
    gamma_val = 2

    table1 = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

    total = 0.0
    while total < times:
        table = [0 for i in range (21)]
        for d1 in range(21):
            if table1[d1]:
               table[d1] = -(1/gamma_val)*math.log((random.random()))
            else:
               table[d1] = -(math.log(random.random()))
      ####Goes on to make new table1 with changes, either all 1's, all 0's or a mix of 0s   #########and 1s

    files1 = 0
    files01 = 0
    files0 = 0

    if "1" "0" in table1 == True:
             files01 += 1
    elif 1 in table == True:
             files1 += 1
    elif 0 in table1 == true:
             files0 += 1
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
kbob
  • 3
  • 1
  • 3
  • premature optimization is the root of (most) evil – GoingTharn Feb 08 '12 at 21:16
  • 3
    Your code has multiple issues that make it hard to give a proper answer. 1. The indentation is broken. Indentation changes the meaning of a program in Python, and without the proper indentation, it's impossible to deduce the proper meaning. 2. `if "1" "0" in table1==True:` is valid, but very strange and most certainly unintended Python code. What is this code supposed to check? 3. You aren't calling the `append()` methods -- your a just looking them up. This way, it is impossible to tell what it is you want to append to the lists. 4. `files1[]` etc. isn't valid Python. – Sven Marnach Feb 08 '12 at 21:16
  • 1
    You're importing two things in the middle of two loops? – Ben Feb 08 '12 at 21:17
  • 1
    @Ben: The imports are strange, but we first have to sort out the more pressing issues with this code. :) – Sven Marnach Feb 08 '12 at 21:19
  • 5
    "what method would be the fastest". Is the least of your concerns. First. Get something to work. Then. If it's too slow. Use the profiler to find out what the slowdown is. "worries that the append function might be too slow" is irrelevant. Don't "worry". Measure. – S.Lott Feb 08 '12 at 21:19
  • `range(0, 499)` creates a list with only 499 items. Do `range(500)` if you want it to loop 500 times. – Joel Cornett Feb 08 '12 at 21:38
  • 2
    It also appears that your `while` loop is infinite. I don't see anywhere in your loop where you adjust the value of either `total` or `times`. – Joel Cornett Feb 08 '12 at 21:42
  • @SvenMarnach, of course :-). In your initial comment you missed looping though float to int and what `files0()` means, or not as the case may be. – Ben Feb 08 '12 at 21:44
  • 1
    Python has a built in function [`all`](http://docs.python.org/library/functions.html#all). For example `all(e == 1 for e in [1, 1, 0])` returns `False`, but `all(e == 1 for e in [1, 1, 1])` returns `True` – Peter Wood Feb 08 '12 at 22:59

3 Answers3

0

There is no speed lost to append(), compared to the speed lost to scanning over things multiple times. And there is very little time lost to memory operations compared to the computations. So don't worry about it. I might not keep the counts, if I can get them from the lengths of the lists you want to accumulate anyway. It is more readable to do everything once. Make the stuff, and then count.

I trust the standard containers relative to making decisions about speed of algorithms. So I would cast the row to a Set and compare to the Set([0]), Set([1]), and Set([0,1]). I assume 'in' will do a double scan of the row, whereas Set() will make one pass.

BOTH = set([0, 1])
results = {'0': [], '1': [], '01': []}

.... make the list ....


elements = set(table)
if elements == BOTH:
    results['01'].append(table)
else if 1 in elements:
    results['1'].append(table)
else:
    results['0'].append(table)

And I will try to make my picking about style, not outright errors:

Use the final else, don't exhaust all the conditions; it really is more readable. Exhausting them all separately makes readers wonder what case you imagine might be left. It breeds paranoia.

In general, actually comparing things to True or False is non-pythonic. Checking equality to the constant True is the least reliable way to get what you want out of an condition in Python. There are a lot of Python idioms that rely on the truth of a statement being represented by the existence of an object, or the non-emptyness of a list. So you will face programmers who return something other than True or False from helper functions to represent Boolean determinations. Get used to not being finicky about it.

Also, painful as it seems, in when mixed with other comparison operators chains as though it meant <, which is so non-idiomatic for non-analysts that you should never do it.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
0

For choosing where to append, create 2 boolean vars (Has1s and Has0s) before the while loop, each initialized to False. Set Has1s to True whenever you get a 1 & Has0s when you get a 0 -- then you avoid the (up to) 3 searches at the end.

Scott Hunter
  • 48,888
  • 12
  • 60
  • 101
  • I doubt that's faster. You'll execute a lot of extra Python code to avoid three "super fast" searches in optimized C code. (I can't time the code because there's no working code...) – Reinstate Monica Feb 08 '12 at 21:31
0

What exactly do you need at the end?

If you just want to know the proportion of all 1's, all 0's, or mixes, it seems more intuitive (to me at least) to just increment variable values, rather than generate lists. If you set up the code something like:

...
files1=0
files01=0
files0=0

if 1 in table1 and 0 in table1:
       files01 += 1
elif 1 in table:
       files1 += 1
elif 0 in table1:
       files0 += 1
...

then you don't have to do a len(files01) at the end to know how many had a mix of 1's and 0's.

  • files1 or files01 or files0 always = 0 I must just have it at the wrong indentation – kbob Feb 08 '12 at 23:53
  • This is totally wrong. "1" "0" concatenates the strings into "10", so you have `"10" in table1==True`. This is also wrong as the expression should be `something in table1`, adding the `==True` changes it. Try in the interpreter and you'll see. I must admit I'm not sure why! – Peter Wood Feb 10 '12 at 08:17
  • Additionally, checking for strings in a list of integers is always going to return `False` – Peter Wood Feb 10 '12 at 08:20
  • Good point @PeterWood - the `if` and `elif` are already returning a `True` or `False`. To get it to check for 1 and 0, you just need to tell it to do both (hurray for python's simplicity) – Keith Yoder Feb 16 '12 at 15:35