Searching for the 'p' value in a coin toss simulation - python

Newbie to coding, attempting to find the 'p' value in a coin toss simulation.
Currently getting the attribute error:
'int' object has no attribute 'sum'.
How could it be? please Help.'''
import numpy as np
import random
attempts = 0
t = 0
for I in range (10000):
attempts = random.randint(2, 30)
if (attempts.sum >= 22 ):
t += 1
p = t / 10000
print(p)

If you are just trying to toss a coin 10,000 times and see how many turn up heads (or tails, if you prefer) then this is a simple way to do it. The random.random function returns a number such that 0 <= x < 1, so 50% of the time it should be less than .5.
import random
tosses = 100000
t = 0
for i in range(tosses):
if random.random() < .5:
t += 1
p = t / tosses
print(p)

attempts is the most recent random integer you generated. An int has no attribute (data field) sum. Since you haven't adequately described what you think your code does, we can't fix the problem.
Python's sum function adds up a sequence of items; see the documentation for examples.
You try to count something with variable m, but you give it no initial value.
You set t to 0, and later divide it by your loop limit, but you've never changed the value; this will be 0.0.
Update after OP comments
I think I understand now: you want to estimate the probability of getting at least 22 heads (or whatever side you choose) in a set of 30 tosses of a fair coin. I'll do my best to utilize your original code.
First of all, you have to toss a fair coin; the function call you made generates a random integer in the range [2, 30]. Instead, you need to do a call such as the below in groups of 30:
flip = random.randint(0,1)
This gives you a 0 or 1. Let's assume that we want to count 1 results: this allows us to simply add the series:
count = sum(random.randint(0,1) for _ in range(30))
This will loop 30 times, put the results in a list, and add them up; there's your count of desired flips. Now, do 10,000 of those 30-flip groups, checking each for 22 results:
import random
t = 0
for i in range (10000):
count = sum(random.randint(0,1) for _ in range(30))
if (count >= 22):
t += 1
p = t / 10000
print(p)
Now, if you want to tighten this even more, use the fact that a successful comparison (i.e. True) will evaluate to 1; False will be 0: make all 10,000 trials in an outer comprehension (in-line for):
t = sum(
sum(random.randint(0,1) for flip in range(30)) > 22
for trial in range(10000) )
print(t / 10000)
flip and trial are dummy loop variables; you can use whatever two you like.
Finally, it's usually better style to make named variables for your algorithms parameters, such as
threshhold = 22
trial_limit = 10000
flip_limit = 30
and use those names in your code.

Related

Finding float average of random list in python

I have looked on several websites, books, and in the documentation and I can't figure out what I am doing wrong. I try to ask for help as a last resort, so that I can learn on my own, but I have spent far too long trying to figure this out, and I am sure it is something really simple that I am doing wrong, but I am learning. The code produces a single different result every time it is ran. The code produces the following error:
26.8
Traceback (most recent call last):
File "main.py", line 7, in
tot = sum(rand)/len(rand)
TypeError: 'float' object is not iterable
import random
for x in range (10000):
rand = random.uniform(10, 100)
print(round(rand, 1))
tot = sum(rand)/len(rand)
print (round(tot, 1))
You're not actually generating a list, you're generating individual values.
Do you really want to print out 10000 values along the way to your final result?
If the answer is "no!", then your code can be reduced to:
import random
N = 10000
print(round(sum(random.uniform(10, 100) for _ in range(N)) / N, 1))
or, if you prefer to break it out a little bit more for readability:
import random
N = 10000
total = sum(random.uniform(10, 100) for _ in range(N))
average = total / N
print(round(average, 1))
If this is beyond the scope of what you've learned, you can create total outside the loop initialized to zero, update it with each new value as you iterate through the loop, and then calculate the final answer:
import random
N = 10000
total = 0.0
for _ in range(N): # use '_' instead of x, since x was unused in your prog
total += random.uniform(10, 100)
average = total / N
print(round(average, 1))
This avoids wasting storage for a list of 10000 values and avoids the append() you're not yet familiar with. Of course, if you need the 10000 values later for some other purpose, you'll need to tuck them away in a list:
import random
N = 10000
l = [random.uniform(10, 100) for _ in range(N)]
total = sum(l)
print(round(total / N, 1))
Addendum
Just for jollies, you can also do this recursively:
import random
def sum_of_rands(n):
if n > 1:
half_n = n // 2
return sum_of_rands(half_n) + sum_of_rands(n - half_n)
elif n == 1:
return random.uniform(10, 100)
N = 10000
print(round(sum_of_rands(N) / N, 1))
print(sum_of_rands(0)) # returns None because nothing is being summed
Splitting the problem in half (on average) in each recursive call keeps the stack to O(log N).
I'd actually advise you to stick with list comprehension or looping, but wanted to show you there are lots of different ways to get to the same result.
In the sum function you must parse an iterable object but you're parsing a float object.
To avoid this error you should put two last lines outside the for loop and append rand to a list. I don't know if it's what you want to do but it shows you how use sum:
import random
l = []
for x in range(10000):
rand = random.uniform(10, 100)
l.append(rand)
print(round(rand, 1))
tot = sum(l)/len(l)
print(round(tot, 1))

My code suddenly stops writing at beyond 15500 iterations

I'm studying how to code in Python and I'm trying to recreate a code I did in college.
The code is based on a 2D Ising model applied to epidemiology. What it does is:
it constructs a 2D 100x100 array using numpy, and assigns a value of -1 to each element.
The energy is calculated based on the function calc_h in the script below.
Then, the code randomly selects a cell from the lattice, changes the value to 1, then calculates the energy of the system again.
Then, the code compares if the energy of the system is less than or equal to the previous configuration. If it does, it "accepts" the change. If it isn't, a probability is compared to a random number to determine if the change is "accepted". This part is done in the metropolis function.
The code repeats the process using a while loop until the maximum specified iteration, max_iterations.
-The code tallies the number of elements with a -1 value (which is the s variable) and the number of elements with a 1 value (which is the i variable) in the countSI function. The script appends to a text file every 500 iteratons.
THE PROBLEM
I ran the script and besides taking too long to execute, the tallying stops at 15500. The code doesn't throw any error, but it just keeps going. I waited for around 3 hours for it to finish but it still goes only up to 15500 iterations.
I've tried commenting out the writing to csv block and instead printing the values first to observe it as it happens, and there I see, it stops at 15500 again.
I have no idea what's wrong as it doesn't throw in any error, and the code doesn't stop.
Here's the whole script. I put a description of what the part does below each block:
import numpy as np
import random as r
import math as m
import csv
init_size = input("Input array size: ")
size = int(init_size)
this part initializes the size of the 2D array. For observation purposes, I selected a 100 by 100 latice.
def check_overflow(indx, size):
if indx == size - 1:
return -indx
else:
return 1
I use this function for the calc_h function, to initialize a circular boundary condition. Simply put, the edges of the lattice are connected to one another.
def calc_h(pop, J1, size):
h_sum = 0
r = 0
c = 0
while r < size:
buffr = check_overflow(r, size)
while c < size:
buffc = check_overflow(c, size)
h_sum = h_sum + J1*pop[r,c] * pop[r,c-1] * pop[r-1,c] * pop[r+buffr,c] * pop[r,c+buffc]
c = c + 1
c = 0
r = r + 1
return h_sum
this function calculates the energy of the system by taking the sum of the product of the value of a cell, its top, bottom, left and right neighbors, multiplied to a constant J.
def metropolis(h, h0, T_):
if h <= h0:
return 1
else:
rand_h = r.random()
p = m.exp(-(h - h0)/T_)
if rand_h <= p:
return 1
else:
return 0
This determines whether the change from -1 to 1 is accepted depending on what calc_h gets.
def countSI(pop, sz, iter):
s = np.count_nonzero(pop == -1)
i = np.count_nonzero(pop == 1)
row = [iter, s, i]
with open('data.txt', 'a') as si_csv:
tally_data = csv.writer(si_csv)
tally_data.writerow(row)
si_csv.seek(0)
This part tallies the number of -1's and 1's in the lattice.
def main():
J = 1
T = 4.0
max_iterations = 150000
population = np.full((size, size), -1, np.int8) #initialize population array
The 2D array is initialized in population.
h_0 = calc_h(population, J, size)
turn = 1
while turn <= max_iterations:
inf_x = r.randint(1,size) - 1
inf_y = r.randint(1,size) - 1
while population[inf_x,inf_y] == 1:
inf_x = r.randint(1,size) - 1
inf_y = r.randint(1,size) - 1
population[inf_x, inf_y] = 1
h = calc_h(population, J, size)
accept_i = metropolis(h,h_0,T)
This is the main loop, where a random cell is selected, and whether the change is accepted or not is determined by the function metropolis.
if (accept_i == 0):
population[inf_x, inf_y] = -1
if turn%500 == 0 :
countSI(population, size, turn)
The script tallies every 500th iteration.
turn = turn + 1
h_0 = h
main()
The expected output is a text file with the tallies of the number of the s and i every 500th iteration. something that looks like this:
500,9736,264
1000,9472,528
1500,9197,803
2000,8913,1087
2500,8611,1389
3000,8292,1708
3500,7968,2032
4000,7643,2357
4500,7312,2688
5000,6960,3040
5500,6613,3387
6000,6257,3743
6500,5913,4087
7000,5570,4430
7500,5212,4788
I have no idea where to start at a solution. At first, I thought it was the writing to csv that's causing the problem, but probing through the print function proves otherwise. I tried to make it as concise as I can.
I hope you guys can help! I really wanna learn this language and start simulating a lot of stuff, and I think this mini project is a great starting step for me.
Thanks a lot!
Answer provided by #randomir in the comments:
Your code is probably wrong. It will block in that nested while loop whenever the number of spins to flip is smaller than the number of iterations. In your example from the previous comment, the size of the population is 10000 and you want to flip 15500 spins. Note that once spin is flipped up (with 100% prob), it will be flipped down with smaller prob, due to metropolis sampling.
works.

Counting how many times I used one equation until it reaches a specific result in python

import math
#entrada
x=int(input("Put a number here:"))
#processo
num1=int(math.sqrt(x))
num2=round(num1,0)
num3=num2**2
remaining=x-num3
#saída
print("The remaining is:",remaining)
I made this code to get the remaining of a perfect square, for any "int" number, now I want to improve on this code so it keeps doing the equation using the last answer(stored in "remaining")is "0"(and stop calculating after that).
And then, after it finishes calculating, I want to count how many times I used the equation until it reaches "0"
I know this is hard to understand put ill try with one example:
For the number 87, the remaining will be 6 in this code because 87-(9²)=6, I want to use this result(6)and make the same equation and then the result will be (2) because 6-(2²)=2, then doing it again (1), then stop once it returns (0).
After that, I want to count how many times the equation was used to reach (0), in this example, it would be 4 (87 6)(6 2)(2 1)(1 0). And I want to print that counting...in this case(4)
I know it is a lot to ask to help me in this(it's a big request), but I'm just staring programming now(10 days ago)and I couldn't find what I wanted anywhere else in the internet. Thanks for the help. Also, if there is any way to make mine original code better tell me please.
I think you need something like this:
def count_squares(x):
count = 0
remaining = 1
while remaining:
min_square = (int(x**0.5) // 1) **2
remaining = x - min_square
count +=1
print('X = {}, remaining = {}, count = {}'.format(x, remaining, count))
x = remaining
return count
print(count_squares(87))
Explaining:
** operator — for exponentiation.
// operator — for floor division. In this case it is similiar to "int" and "round" bound, that you used for calculating num2, because "//1" will throw away all digits after dot. By the way int() function is not necessary in this case at all.
we will exit from while loop as soon as remaining value will be equal to zero, because zero integer value is interpreted as false.
format is method of strings used to do formatting(surprisingly). All {} will be filled with arguments passed to the "format" method. There are other ways to do formatting in python( % operator, and formatted strings).
Output is:
X = 87, remaining = 6, Count = 1
X = 6, remaining = 2, Count = 2
X = 2, remaining = 1, Count = 3
X = 1, remaining = 0, Count = 4
4

Using python how do I repeatedly divide a number by 2 until it is less than 1.0?

I am unsure of how to create the loop to keep dividing the number by two? Please help. I know you you can divide a number by 2 don't know how to create the loop to keep dividing until it is less than 1.0.
It depends on what exactly you're after as it isn't clear from the question. A function that just divides a number by zero until it is less than 1.0 would look like this:
def dividingBy2(x):
while x > 1.0:
x = x/2
But this serves no purpose other than understanding while loops, as it gives you no information. If you wanted to see how many times you can divide by 2 before a number is less than 1.0, then you could always add a counter:
def dividingBy2Counter(x):
count = 0
while x > 1.0:
x = x/2
count = count + 1
return count
Or if you wanted to see each number as x becomes increasingly small:
def dividingBy2Printer(x):
while x > 1.0:
x = x/2
print(x)
b=[] #initiate a list to store the result of each division
#creating a recursive function replaces the while loop
#this enables the non-technical user to call the function easily
def recursive_func(a=0): #recursive since it will call itself later
if a>=1: #specify the condition that will make the function run again
a = a/2 #perform the desired calculation(s)
recursive_func(a) #function calls itself
b.append(a) #records the result of each division in a list
#this is how the user calls the function as an example
recursive_func(1024)
print (b)

Exploring Python Exercise

I am learning Python from the book Exploring Python by Timothy Budd. One of the exercises from this chapter is this:
15. The function randint from the random module can be used to produce random numbers. A call on random.randint(1, 6), for example, will produce the values 1 to 6 with equal probability. Write a program that loops 1000 times. On each iteration it makes two calls on randint to simulate rolling a pair of dice. Compute the sum of the two dice, and record the number of times each value appears. Afterthe loop, print the array of sums. You can initialize the array using the idiom shown earlier in this chapter:
times = [0] * 12 # make an array of 12 elements, initially zero
I am able to print the sum in the array, but I have not understood the concept of recording the number of times each value appears. Also, what purpose would times = [0] serve? Here is my code for printing the sum:
#############################################
# Program to print the sum of dice rolls #
#############################################
from random import randint
import sys
times = [0] * 12
summation = []
def diceroll():
print "This program will print the"
print "sum of numbers, which appears"
print "after each time the dice is rolled."
print "The program will be called 1000 times"
for i in range(1,1000):
num1 = randint(1,6)
num2 = randint(1,6)
sum = num1 + num2
summation.append(sum)
#times[i] = [i] * 12
print summation
#print times
diceroll()
times[0] * 12 initiates a list of 12 elements with value 0. What you want to do next is
times[s] += 1 #adds 1 to the number of times s occurs
This is similar to using a dict to encode a value, but its simpler.
times = [0] initializes a list called times of length 1 and value 0. The idiom times = [0] * 12 means times is a list of 12 zeroes.
If you want to be able to use this without keyerror when num1==num2==6, you need to do times = [0]*13 because python is a 0 indexed system.
Sidenote: Don't use sum as a variable name because it is a builtin function (predefined) and you don't want to override it. Use times[sum([num1,num2])] += 1 or times[num1+num2] instead.
To count number of occurrences:
times = [0]*13
for _ in range(1000):
sum_ = randint(1, 6) + randint(1, 6)
times[sum_] += 1
print(times[2:])
Possible values of sum_ are 2...12 including. Possible times indexes are 0...12 including.
times[i] corresponds to a number of occurrences of sum_ == i among 1000 tries.
Note: times[0] and times[1] are always zero because sum_ > 1
[x]*3 produces [x, x, x] It is a nicer version of:
L = []
L.append(x)
L.append(x)
L.append(x)
Additional comments about your code:
print something is an error on Python 3
for i range(1, 1000) is wrong. It produces i from 1 to 999 including (999 iterations instead of 1000 as required). range doesn't include upper limit as it customery for intervals in programming.

Categories