Different Result when calculating Polepairs with Octave vs Python - python-3.x

I am trying to calculate pole pairs with both Octave 5.1.10 and Python 3.8.
The Octave code:
wc=1
n=4
s={n}
G=1
function poles (n, wc, G)
s={n}
for k =1:n
s{k}=wc*e^((j*(2*k+n-1)*pi)/(2*n))
endfor
endfunction
The ouput is:
s =
{
[1,1] = -0.38268 + 0.92388i
[1,2] = -0.92388 + 0.38268i
[1,3] = -0.92388 - 0.38268i
[1,4] = -0.38268 - 0.92388i
}
The Python code:
import numpy as np
import math
wc=1
n=4
G=1
def poles (n, wc, G):
import math
s=[] #contains the complex polpairs
e=math.e
pi=math.pi
for k in range(n):
s.append(wc*e**((1j*(2*k+n-1)*pi)/(2*n)))
return s
returns
s=[
(0.38268343236508984 + 0.9238795325112867j),
(-0.3826834323650897 + 0.9238795325112867j),
(-0.9238795325112867 + 0.3826834323650899j),
(-0.9238795325112868 - 0.38268343236508967j)]
Can someone explain to me why these two outputs are different?

In your octave loop, k takes values from 1 to 4.
In your python loop, k takes values from 0 to 3
If you want the same behaviour in your python loop, change
for k in range(4):
to
for k in range(1, 5):

Related

How to find minima and maxima of a function. I am limited to using numpy, sympy and matplotlib

I am asked to find the maxima and minima of few functions. One of the functions is y = (9x^3) - (7x^2) + (3x) + 10
The code I could write so far is:
from sympy import*
import matplotlib.pyplot as plt
x = symbols ('x')
f = (9*x**3) - (7*x**2) + (3*x) + 10
intervals = np.arange(-5, 7)
df = diff(f, x)
df2 = diff(f, x, 2)
f = lambdify (x, f)
y = f(intervals)
print (intervals)
print (y)
I am new to using these 3 libraries so I dont know how to find the answer using these 3 libraries
SymPy can tell you the derivative and f and can tell you when a function is zero. Since max/min occur when the derivative is zero you can find the zeros and then determine if those values make the 2nd derivative positive or negative, e.g.
>>> from sympy import real_roots
>>> from sympy.abc import x
>>> f = -x**2 + 1
>>> d1 = f.diff(x)
>>> d2 = d1.diff(x) # = f.diff(x,2)
>>> extrema = real_roots(d1)
>>> for i in extrema:
... if d2.subs(x, i).is_positive:
... print('minimum',i)
... else:
... print('maxima',i)
See also here. (If there are no real roots then there are no extrema for real values of x.)
If you want to pass the values of intervals into the formula and then get the minimum value, you can specify the intervals firstly and then just put this array into the formula instead x:
intervals = np.random.permutation(10)
# [8 4 3 0 2 7 9 1 6 5]
f = (9 * intervals ** 3) - (7 * intervals ** 2) + (3 * intervals) + 10
# [4194 486 199 10 60 2775 6031 15 1720 975]
f.argmin() # --> will get index of the minimum value
# 3
f.min() # --> will get minimum value resulted by the formula
# 10
or if you want to use the formula many times, you can define it as a function and just call it every time you need instead writing it again as:
def formula_1(x):
return (9 * x ** 3) - (7 * x ** 2) + (3 * x) + 10
results = formula_1(intervals)
results.min()

multprocessing for a stochastic process with multiple arguments

I want to solve a stochastic differential equation using multiprocessing. A simplified not-parallel code is like:
import numpy as np
x = np.zeros((2, 3, 4)) #matrix
z = np.random.normal(0, 1, (2,3,4)) #noise
z_array = z
for i in range(2):
for j in range(3):
x[i,j,0] = i
for k in range(3):
x[i,j,k+1] = x[i,j,k]*z_array[i,j,k]
The outcomes are the noisez_array and the corresponding matrix x. I want to use multiprocessing for the second loop. The problem is that I don't know how to incorporate the noise z in the parallel code. A naive implementation is like
import os
import numpy as np
import functools as ft
from multiprocess import Pool
def fun(i, k):
x = np.zeros(4)
x[0] = i
for k in range(2):
z = np.random.normal(0, 1)
x[k+1] = x[k]*z
return x
if __name__=='__main__':
pool = Pool(os.cpu_count()-1)
x = np.zeros((2, 3, 4))
for i in range(2):
result = np.array(pool.map(ft.partial(fun, i), range(3)))
x[i] = result
pool.close()
pool.join()
Since the code involves random numbers, I am not sure whether parallel code is correct or not and I don't know how to get the noises z. Any ideas?
You can try pre-generating the noise z and passing it to the argument along with k as a tuple. That way you have the noise with you and you do not need to generate it in the function. You can also add the first loop with i in the original function in the tuple to run it in the multiprocessing code.
For the code below:
In the second code you wrote, you ran the k loop inside the fun as range(2), which I assume is a typo and I am keeping it till range(3) as in the original code
I have incorporated the first loop into the multiprocessing setup too
If memory is not an issue and the matrix is small, use the below option which is cleaner and the equivalency of your original code and multiprocessing code is easier to read. If memory is an issue, you can compute only smaller matrices inside the fun and then reshape the result rather than adding (let me know if you want that solution).
Main code:
import os
import numpy as np
from multiprocessing import Pool
def fun(t):
i, j, z = t
x = np.zeros((2, 3, 4))
x[i, j, 0] = i
for k in range(3):
x[i, j, k + 1] = x[i, j, k] * z[k]
return x
if __name__=='__main__':
z = np.random.normal(0, 1, (2,3,4))
pool = Pool(os.cpu_count() - 1)
map_args = ((i, j, z[i, j, :]) for i in range(2) for j in range (3))
result = np.array(pool.map(fun, map_args))
x = np.sum(result, 0)
pool.close()
pool.join()

The code is running but there is not output showing

The code is being executed but the output is not shown nor the variables are created
import numpy as np
def magicsquares():
n=input('enter the order of squares')
n=int(n)
m=np.zeros((n,n))
s=n*(n**2+1)/2 #sum of each row or diagonal
p=int(n/2)
q=(n-1)
for i in range(n**2):
m[p][q]=1 #assigning postion of 1
P=p-1
Q=q+1
if(i>=2): #assigning remaining positions
if(P==-1):
P=n-1
if(Q==n):
Q=0
there is not output showing because you are just declaring the function but not calling the function and there is no print/return inside the function. Here is a solution which you can use to see the output and work on:
import numpy as np
def magicsquares():
n = input('enter the order of squares')
n = int(n)
m = np.zeros((n, n))
s = n*(n**2+1)/2 # sum of each row or diagonal
p = int(n/2)
q = (n-1)
for i in range(n**2):
m[p][q] = 1 # assigning postion of 1
P = p-1
Q = q+1
if i >= 2: # assigning remaining positions
if P == -1:
P = n-1
if Q == n:
Q = 0
print(m)
magicsquares()
It is not the ultimate solution to find magic_square. It's just an updated version of your code so that you can see the outputs and work on.

Cubic Polynomial in Python

For my latest project in my coding class (python), we need to program and compute a cubic function. So something like 3x^3+2x^2+7x+1. I cannot figure out how to code in the different x powers. I know this is a very simple question, but I can't find what I am looking for on the internet and have searched. How would I write out this polynomial given the 3,2,7 & 1 values? I assume I need to use numpy but can only figure that out with a degree one polynomial.
powers can be represented with ** in python (there is also a more sophisticated pow) function:
def f(x):
return 3*x**3 + 2*x**2 + 7*x + 1
(in python ^ is the xor operator; if you use your expression python would not complain but just not calculate what you want)
if you need to be able to do symbolic math, i suggest you install the sympy package:
from sympy import symbols
def f(x):
return 3*x**3 + 2*x**2 + 7*x + 1
x = symbols('x')
print(f(x)) # 3*x**3 + 2*x**2 + 7*x + 1
print(f(x).subs(x, 5)) # 461
You can also create a custom function like this example:
def cubic(x, args):
args_len = len(args)
for k in args:
yield k * x ** (args_len-1)
args_len -=1
Demo:
user_input = [3, 2, 7, 1]
user_var_x = 1
somme = sum(cubic(user_var_x, user_input))
print(somme)
Output:
13

Smoothing values (neighbors between 1-9)

Instructions: Compute and store R=1000 random values from 0-1 as x. moving_window_average(x, n_neighbors) is pre-loaded into memory from 3a. Compute the moving window average for x for the range of n_neighbors 1-9. Store x as well as each of these averages as consecutive lists in a list called Y.
My solution:
R = 1000
n_neighbors = 9
x = [random.uniform(0,1) for i in range(R)]
Y = [moving_window_average(x, n_neighbors) for n_neighbors in range(1,n_neighbors)]
where moving_window_average(x, n_neighbors) is a function as follows:
def moving_window_average(x, n_neighbors=1):
n = len(x)
width = n_neighbors*2 + 1
x = [x[0]]*n_neighbors + x + [x[-1]]*n_neighbors
# To complete the function,
# return a list of the mean of values from i to i+width for all values i from 0 to n-1.
mean_values=[]
for i in range(1,n+1):
mean_values.append((x[i-1] + x[i] + x[i+1])/width)
return (mean_values)
This gives me an error, Check your usage of Y again. Even though I've tested for a few values, I did not get yet why there is a problem with this exercise. Did I just misunderstand something?
The instruction tells you to compute moving averages for all neighbors ranging from 1 to 9. So the below code should work:
import random
random.seed(1)
R = 1000
x = []
for i in range(R):
num = random.uniform(0,1)
x.append(num)
Y = []
Y.append(x)
for i in range(1,10):
mov_avg = moving_window_average(x, n_neighbors=i)
Y.append(mov_avg)
Actually your moving_window_average(list, n_neighbors) function is not going to work with a n_neighbors bigger than one, I mean, the interpreter won't say a thing, but you're not delivering correctness on what you have been asked.
I suggest you to use something like:
def moving_window_average(x, n_neighbors=1):
n = len(x)
width = n_neighbors*2 + 1
x = [x[0]]*n_neighbors + x + [x[-1]]*n_neighbors
mean_values = []
for i in range(n):
temp = x[i: i+width]
sum_= 0
for elm in temp:
sum_+= elm
mean_values.append(sum_ / width)
return mean_values
My solution for +100XP
import random
random.seed(1)
R=1000
Y = list()
x = [random.uniform(0, 1) for num in range(R)]
for n_neighbors in range(10):
Y.append(moving_window_average(x, n_neighbors))

Resources