I am trying to run the following script. My intention was to get the output which will give one high intensity gauss in the middle followed by two small gauss on both side of the big one. It is a Fourier summation of all the y values taking different n values each time and plotting them against x. But somehow, I am not getting the desired result. Some help would be appreciated. the code-
from pylab import *
n = 6
D = 6
x = linspace(-3, 3, 13000)
y = [1, 1, 1, 1, 1]
F = []
for i in range(1,n):
F=sum((item*cos(2*pi*i*x/D)for item in y))
plot(x,F,'r')
show()
You are reassigning F each time through the loop. This might be your problem, since at the end of your loop for i in range(1,n) you have F as a number, and not as a list of numbers.
To create a list of F values, simply change F = sum(....) to F.append(sum(...)) and you will end up with a list of values at the end.
Also please note that range(1, n) is the range from 1 to n-1. This may or may not be what you desired.
Related
I've read that one of the key beliefs of Python is that flat > nested. However, if I have several variables counting up, what is the alternative to multiple for loops?
My code is for counting grid sums and goes as follows:
def horizontal():
for x in range(20):
for y in range(17):
temp = grid[x][y: y + 4]
sum = 0
for n in temp:
sum += int(n)
print sum # EDIT: the return instead of print was a mistype
This seems to me like it is too heavily nested. Firstly, what is considered to many nested loops in Python ( I have certainly seen 2 nested loops before). Secondly, if this is too heavily nested, what is an alternative way to write this code?
from itertools import product
def horizontal():
for x, y in product(range(20), range(17)):
print 1 + sum(int(n) for n in grid[x][y: y + 4])
You should be using the sum function. Of course you can't if you shadow it with a variable, so I changed it to my_sum
grid = [range(20) for i in range(20)]
sum(sum( 1 + sum(grid[x][y: y + 4]) for y in range(17)) for x in range(20))
The above outputs 13260, for the particular grid created in the first line of code. It uses sum() three times. The innermost sum adds up the numbers in grid[x][y: y + 4], plus the slightly strange initial value sum = 1 shown in the code in the question. The middle sum adds up those values for the 17 possible y values. The outer sum adds up the middle values over possible x values.
If elements of grid are strings instead of numbers, replace
sum(grid[x][y: y + 4])
with
sum(int(n) for n in grid[x][y: y + 4]
You can use a dictionary to optimize performance significantly
This is another example:
locations = {}
for i in range(len(airports)):
locations[airports["abb"][i][1:-1]] = (airports["height"][i], airports["width"][i])
for i in range(len(uniqueData)):
h, w = locations[uniqueData["dept_apt"][i]]
uniqueData["dept_apt_height"][i] = h
uniqueData["dept_apt_width"][i] = w
I'm quite a programming noob and I've only been using Python more intensively for a few weeks, however, I currently need it for an application in statistics, I am trying to do the following:
Create an array of integers N from 1 up to Q=A q (so N=[1,2,...,Q-1,Q]), and use this to create and plot an array with values for the function P(N) which sums over binomial coefficients. A and q are integer constants (N>q is in there as a true/false statement on purpose). I currently have the following code:
#Constants {A,Q,S,sigma} are set
q=Q/A
n = np.linspace(1,Q,Q,dtype=int) #variable array
Sum = np.zeros((1,Q))
Iteration = np.zeros((1,Q))
alpha = 0
while alpha < A:
alpha=alpha+1
Iteration = sigma^alpha * (comb(n-1,alpha-1) -(n>q)*alpha*comb( max(0,n-q-1), alpha-1) )
Sum = Sum + Iteration
This returns a typeError "only integer scalar arrays can be converted to a scalar index" in the line "Iteration=..." (and probably in the next line as well), and I can't find out what exactly the problem is and how to fix this.
Also; I might be doing the summation in a convoluted way; if there is a better way to sum over this in python, help to that end are also welcome.
Thanks in advance for any help!
The problem comes from the following line:
Iteration = sigma^alpha * (comb(n-1,alpha-1) -(n>q)*alpha*comb( max(0,n-q-1), alpha-1) )
As the parameters for comb has to be two non negative integers, see here, when you pass in n, which is an ndarray, to comb it will return the TypeError you mentioned.
Potentially you could wrap around the while loop and make it a function? Then you can iterate it and append the result to a list.
def this_fun(n):
Sum = 0
Q = 1000
A = 100
sigma = 1
q = int(Q / A)
alpha = 0
while alpha < A:
alpha = alpha+1
Iteration = sigma^alpha * (comb(n-1,alpha-1) -(n>q)*alpha*comb( max(0,n-q-1), alpha-1) )
Sum += Iteration
return Sum
P_N=[]
N = 100
for i in range(1,N):
P_N.append(this_fun(i))
You have to double check the logic on the Iteration line to make sure you are implementing what the maths notication is intended to and put in some sensible value for Q, A and N.
The function looks as if I plot P_N against N, is it what you are expecting?
I am trying to eliminate some non zero entries in a matrix where the 2 adjacent diagonals to the main diagonal are nonzero.
h = np.zeros((n**2,n**2))
for i in np.arange(0, n**2):
for j in np.arange(0,n**2):
if(i==j):
for i in np.arange(0,n**2,n):
h[i,j-1] = 0
print(h)
I want it to only eliminate the lower triangle non-zero entries, but it's erasing some entries in the upper triangle. I know this is because on the last if statement with the for loop, it is iterating for both arguments of the array, when I only want it to iterate for the first argument i, but since I set i=j, it runs for both.
The matrix I want to obtain is the following:
Desired matrix
PS: sorry for the extremely bad question format, this is my first question.
hamiltonian = np.zeros((n**2,n**2)) # store the Hamiltonian
for i in np.arange(0, n**2):
for j in np.arange(0,n**2):
if abs(i-j) == 1:
hamiltonian[i,j] = 1
Is this what you are looking for?:
hamiltonian[0,1] = 1
hamiltonian[n**2-1,n**2-2] = 1
for i in np.arange(1, n**2-1):
hamiltonian[i,i+1] = 1
hamiltonian[i,i-1] = 1
*The instruction is as following:
plotRandomUniformSum(M, N, nBins)
Let’s consider what happens when we add M uniform random numbers together. Since each random number can be between 0 and 1, we expect this sum will be between 0 and M, but somehow we expect that it is more likely for the sum to be near the middle (M/2) than near the ends (0 and M) for M > 1. First write a function randomUniformSum(M) that adds up M uniform random numbers between 0 and 1. Second, write a function that forms a list of N such numbers by calling randomUniformSum a total of N times. Third, plot the result in a histogram and return the list.
Remember that return means to exit the function. Therefore, you should first plot the histogram and then return the list.
What values should you use for binMin and binMax?
To answer this, consider the minimum and maximum values that randomUniformSum may assume. Try calling your function four times with M = 1, 2, 3, 10 setting N = 1000000 and nBins = 100 in each case. You will notice that as M increases, the distribution looks more and more like a Normal (or Gaussian) distribution. This is an illustration of the Central Limit Theorem, a very important theorem from Statistics which states that as you add more and more independent random variables (from any distribution, doesn’t have to be uniform) the sum approaches a Normal distribution - very cool :-).*
This is what I have so far:
def randomUniformSum(M):
sum = 0
for i in range(M):
sum += random.uniform(0,1)
return sum
def plotRandomUniformSum(M, N, nBins):
L = []
for i in range(N+1):
x = randomUniformSum(M)
L.append(x)
hist.plotHistogram(L, nBins = nBins)
My autograder for this assignment returns an error that:
"Test Failed: None != [0.793340083761663, 0.8219540423197268, 0[202687
chars]9087]"
with different numbers for all tests.
Where is my error? I can't seem to find where I went wrong.
You're not returning the list from the plotRandomUniformSum(M, N, nBins) function
def randomUniformSum(M):
sum = 0
for i in range(M):
sum += random.uniform(0,1)
return sum
def plotRandomUniformSum(M, N, nBins):
L = []
for i in range(N+1):
x = randomUniformSum(M)
L.append(x)
hist.plotHistogram(L, nBins = nBins)
return L # you missed this out
list_of_random_sums = plotRandomUniformSum(10, 1000000, 100)
Second, write a function that forms a list of N such numbers by calling randomUniformSum a total of N times.
Hello, welcome to SO. For me it seems unclear that you've formed a list consisting of N+1 elements instead of N. Try to change for i in range(N+1): line with for i in range(N):.
This is what I have imported:
import random
import matplotlib.pyplot as plt
from math import log, e, ceil, floor
import numpy as np
from numpy import arange,array
import pdb
from random import randint
Here I define the function matrix(p,m)
def matrix(p,m): # A matrix with zeros everywhere, except in every entry in the middle of the row
v = [0]*m
v[(m+1)/2 - 1] = 1
vv = array([v,]*p)
return vv
ct = np.zeros(5) # Here, I choose 5 cause I wanted to work with an example, but should be p in general
Here I define MHops which basically takes the dimensions of the matrix, the matrix and the vector ct and gives me a new matrix mm and a new vector ct
def MHops(p,m,mm,ct):
k = 0
while k < p : # This 'spans' the rows
i = 0
while i < m : # This 'spans' the columns
if mm[k][i] == 0 :
i+=1
else:
R = random.random()
t = -log(1-R,e) # Calculate time of the hopping
ct[k] = ct[k] + t
r = random.random()
if 0 <= r < 0.5 : # particle hops right
if 0 <= i < m-1:
mm[k][i] = 0
mm[k][i+1] = 1
break
else:
break # Because it is at the boundary
else: # particle hops left
if 0 < i <=m-1:
mm[k][i] = 0
mm[k][i-1] = 1
break
else: # Because it is at the boundary
break
break
k+=1
return (mm,ct) # Gives me the new matrix showing the new position of the particles and a new vector of times, showing the times taken by each particle to hop
Now what I wanna do is iterating this process, but I wanna be able to visualize every step in a list. In short what I am doing is:
1. creating a matrix representing a lattice, where 0 means there is no particle in that slot and 1 means there is a particle there.
2. create a function MHops which simulate a random walk of one step and gives me the new matrix and a vector ct which shows the times at which the particles move.
Now I want to have a vector or an array where I have 2*n objects, i.e. the matrix mm and the vector ct for n iterations. I want the in a array, list or something like this cause I need to use them later on.
Here starts my problem:
I create an empty list, I use append to append items at every iteration of the while loop. However the result that I get is a list d with n equal objects coming from the last iteration!
Hence my function for the iteration is the following:
def rep_MHops(n,p,m,mm,ct):
mat = mm
cct = ct
d = []
i = 0
while i < n :
y = MHops(p,m,mat,cct) # Calculate the hop, so y is a tuple y = (mm,ct)
mat = y[0] # I reset mat and cct so that for the next iteration, I go further
cct = y[1]
d.append(mat)
d.append(cct)
i+=1
return d
z = rep_MHops(3,5,5,matrix(5,5),ct) #If you check this, it doesn't work
print z
However it doesn't work, I don't understand why. What I am doing is using MHops, then I want to set the new matrix and the new vector as those in the output of MHops and doing this again. However if you run this code, you will see that v works, i.e. the vector of the times increases and the matrix of the lattice change, however when I append this to d, d is basically a list of n equal objects, where the object are the last iteration.
What is my mistake?
Furthermore if you have any coding advice for this code, they would be more than welcome, I am not sure this is an efficient way.
Just to let you understand better, I would like to use the final vector d in another function where first of all I pick a random time T, then I would basically check every odd entry (every ct) and hence check every entry of every ct and see if these numbers are less than or equal to T. If this happens, then the movement of the particle happened, otherwise it didn't.
From this then I will try to visualize with matpotlibt the result with an histogram or something similar.
Is there anyone who knows how to run this kind of simulation in matlab? Do you think it would be easier?
You're passing and storing by references not copies, so on the next iteration of your loop MHops alters your previously stored version in d. Use import copy; d.append(copy.deepcopy(mat)) to instead store a copy which won't be altered later.
Why?
Python is passing the list by reference, and every loop you're storing a reference to the same matrix object in d.
I had a look through python docs, and the only mention I can find is
"how do i write a function with output parameters (call by reference)".
Here's a simpler example of your code:
def rep_MHops(mat_init):
mat = mat_init
d = []
for i in range(5):
mat = MHops(mat)
d.append(mat)
return d
def MHops(mat):
mat[0] += 1
return mat
mat_init = [10]
z = rep_MHops(mat_init)
print(z)
When run gives:
[[15], [15], [15], [15], [15]]
Python only passes mutable objects (such as lists) by reference. An integer isn't a mutable object, here's a slightly modified version of the above example which operates on a single integer:
def rep_MHops_simple(mat_init):
mat = mat_init
d = []
for i in range(5):
mat = MHops_simple(mat)
d.append(mat)
return d
def MHops_simple(mat):
mat += 1
return mat
z = rep_MHops_simple(mat_init=10)
print(z)
When run gives:
[11, 12, 13, 14, 15]
which is the behaviour you were expecting.
This SO answer How do I pass a variable by reference? explains it very well.