Related
hello I am newbie at python and coding for the most part and I have 5 ordinary differential equations.(non-linear) that I want to model and have them plot. I have the parameters that are given, my main issue has been setting the independent variables to be a function of z. As well as setting the 'S' parameters to be a function of time since they vary depending on the time of year.
edited CODE
I've been able to have the code run with set parameters. I now wonder how I could take these parameters and make them behave at different times. The parameters that are set on this code are for a specific amount of "days" during the year. They are not meant to be consistent throughout. How could I implement time to have them be dependent on it?
import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt
import math
from math import e
def func(z,t):
xh, xf, y, m, n = z
v1,v2,v3 = 0.05,0.06,0.07
B1,B2,B3 = 0.1984,0.1593,0.04959
d1,d2,d3 = 0.02272,0.02272,0.2
o1,o2 = 0.25,0.75
S1=S2=S3=0.005
S4=S5=0.3
p = 0
u = 500
k = 0.000075
a = 0.4784
r = 0.0165
K = 8000
i = 2
H = e**(-m*k)
g = ((xh+xf)**i)/((K**i)+((xh+xf)**i))
R = o1-(o2*(xf/(xh+xf+.002)))
P1 =(xh+xf)/(xh+y+xf+.002)
P2 = 1-((m+n)/(a*(xh+y+xf+.002)))
P3 = y/(xh+y+xf+.002)
dxhdt = (u*g*H)-(B1*(m*(xh/(xh+y+xf+.002))))-((d1+S1)*xh)-((v1*(m+n))*xh)-(xh*R)
dxfdt = (xh*R)-(B1*(m*(xf/(xh+y+xf+.002))))-((p+d2+S2)*xf)-(v2*(m+n)*xf)
dydt = (B1*(m*P1))-((d3+S3)*y)-((v3*(m+n))*y)
dmdt =(r*(m*P2))+(B2*(n*P3))-(B3*(m*P1))-(S4*m)
dndt = (r*(n*P2))-(B2*(n*P3))+(B3*(m*P1))-(S5*n)
return [dxhdt,dxfdt,dydt,dmdt,dndt]
z0=[13000,11000,0,0,0]
t = np.linspace(0,100,1000)
xx=odeint(func,z0,t)
plt.figure(1)
plt.plot(t,xx[:,0],'b-',label = 'xh')
plt.plot(t,xx[:,1],'y-',label = 'xf')
plt.plot(t,xx[:,2],'g-',label = 'y')
plt.plot(t,xx[:,3],'r-',label = 'm')
plt.plot(t,xx[:,4],'m-',label = 'n')
plt.legend()
plt.ylabel('POPULATION')
plt.xlabel('TIME')
plt.show()
I though about creating two different functions and looping the plot. How do you makes "days" of function of t? just declaring it is? I get error code "TypeError: 'float' object cannot be interpreted as an integer"
z0=[13000,11000,0,0,0]
t = np.linspace(0,91.25,1000)
xx=odeint(func,z0,t)
xy=odeint(func2,z0,t)
plt.figure(1)
for t in range(1,91.25):
plt.plot(t,xx[:,0],'b-',label = '$x_h$')
plt.plot(t,xx[:,1],'y-',label = '$x_f$')
plt.plot(t,xx[:,2],'g-',label = 'y')
plt.plot(t,xx[:,3],'r-',label = 'm')
plt.plot(t,xx[:,4],'m-',label = 'n')
for t in range(91.25,182.50):
plt.plot(t,xy[:,0],'b-',label = '$x_h$')
plt.plot(t,xy[:,1],'y-',label = '$x_f$')
plt.plot(t,xy[:,2],'g-',label = 'y')
plt.plot(t,xy[:,3],'r-',label = 'm')
plt.plot(t,xy[:,4],'m-',label = 'n')
plt.legend()
plt.ylabel('POPULATION')
plt.xlabel('TIME')
plt.show()
I get what you mean by an ODE, but please expand it so others that are not cognizant of mathematics can understand.
If you want these to be a function of z, then you must declare a function something() and assign the variables this function. This way, your values will change with respect to changes in z.
Also by convention, I don't recommend using this much of variable declarations. Abstract these as much as possible. As an alternative, you can declare similar variables in the same line, like
v1, v2, v3 = 0.5, 0.6, 0.7
etc. This will make it much more readable.
If you don't have any syntax error due to multiple assignments in the first line, I recommend change each of this to be a function of z. Divide your bigger function to smaller chunks, make each of this a different function. This way you can manipulate results directly and code will be much more readable.
You prefer the state vector to be composed as
xh, xf, y, m, n
This interpretation of the state vector then needs to be applied everywhere, which means that you have to change the first line of the ODE function to
xh, xf, y, m, n = z
Also check that your fractions are implemented as they were in paper, esp. P1 appears suspicious. But without the genesis of the equation I can not say that it is wrong as it is.
I have an assignment for my Applied Computer Science class in which we are to test the strength and qualities of an algorithm that tries to find the k:th highest value in a list. This is to be tested both for varying k:s (0, 1, 2, ..., k=N), and varying N:s where I have chosen k=0 and N (1, 2, ..., N). We're supposed to determine whether the algorithm ever makes more than pi*N comparisons as well as log2(N/2 - k)*N comparisons.
To find some clarity in this I made two plots, both having number of comparisons as the y-axis, and k and N respectively for the x-axis. Alongside the plots I want the functions y = pi*N and y = log2(N/2 - k)*N. The problem is I get a ValueError for the second function, most definitely when N/2 = k. I would still like to plot it in python and my question is how to get around this.
The rest of the code isn't really relevant.
My question is: how can I plot this function while circumventing it's undefined parts? I still want to illustrate the undefined part so I don't want to make exceptions in which a simplification is made.
def plotHelper(x, yA, yS, title, trials):
yPi = list()
yLogN = list()
for point in x:
yPi.append(point*math.pi)
yLogN.append((trials*math.log(trials/2 - point, 2)
plt.figure()
plt.title(title)
plt.plot(x, yA)
plt.plot(x, yS)
plt.plot(x, yPi)
plt.plot(x, yLogN)
plt.grid(True)
plt.legend(["Mean", "Standard Deviation", "y = pi * N"])
plt.ylabel("Comparisons")
plt.xlabel("k")
plt.show()
def plot():
choice = initiate()
yA, yS, trials = trialFunc(choice)
x = range(0, trials)
f_of_k = "Comparisons as a function of desired k (N elements)"
f_of_n = "Comparisons as a function of elements (k = 0)"
if choice:
title = f_of_k
else:
title = f_of_n
plotHelper(x, yA, yS, title, trials)
If you cannot represent a value of a function as a number, you can represent it as a Not-a-Number aka NaN. There's no ready-made constant for it, but you can easily produce that value:
NaN = float('NaN')
Now your function can go like this:
def function_to_plot(n): # A contrived example.
if abs(n) <= 1:
return NaN
return sqrt(n * n - sin(n) ** 2)
After that, matplotlib just works, it knows how to skip points that are NaNs.
If you just want to tabulate your function by hand, you can safely print NaNs using format for floats.
For a bit more detail, you can use float('+inf') and float('-inf') to represent infinities.
Also, just in case, Python works fine with complex numbers; import cmath and do things like assert cmath.sqrt(-2j) == (1-1j).
When using scipy.ndimage.interpolation.shift to shift a numpy data array along one axis with periodic boundary treatment (mode = 'wrap'), I get an unexpected behavior. The routine tries to force the first pixel (index 0) to be identical to the last one (index N-1) instead of the "last plus one (index N)".
Minimal example:
# module import
import numpy as np
from scipy.ndimage.interpolation import shift
import matplotlib.pyplot as plt
# print scipy.__version__
# 0.18.1
a = range(10)
plt.figure(figsize=(16,12))
for i, shift_pix in enumerate(range(10)):
# shift the data via spline interpolation
b = shift(a, shift=shift_pix, mode='wrap')
# plotting the data
plt.subplot(5,2,i+1)
plt.plot(a, marker='o', label='data')
plt.plot(np.roll(a, shift_pix), marker='o', label='data, roll')
plt.plot(b, marker='o',label='shifted data')
if i == 0:
plt.legend(loc=4,fontsize=12)
plt.ylim(-1,10)
ax = plt.gca()
ax.text(0.10,0.80,'shift %d pix' % i, transform=ax.transAxes)
Blue line: data before the shift
Green line: expected shift behavior
Red line: actual shift output of scipy.ndimage.interpolation.shift
Is there some error in how I call the function or how I understand its behavior with mode = 'wrap'? The current results are in contrast to the mode parameter description from the related scipy tutorial page and from another StackOverflow post. Is there an off-by-one-error in the code?
Scipy version used is 0.18.1, distributed in anaconda-2.2.0
It seems that the behaviour you have observed is intentional.
The cause of the problem lies in the C function map_coordinate which translates the coordinates after shift to ones before shift:
map_coordinate(double in, npy_intp len, int mode)
The function is used as the subroutine in NI_ZoomShift that does the actual shift. Its interesting part looks like this:
Example. Lets see how the output for output = shift(np.arange(10), shift=4, mode='wrap') (from the question) is computed.
NI_ZoomShift computes edge values output[0] and output[9] in some special way, so lets take a look at computation of output[1] (a bit simplified):
# input = [0,1,2,3,4,5,6,7,8,9]
# output = [ ,?, , , , , , , , ] '?' == computed position
# shift = 4
output_index = 1
in = output_index - shift # -3
sz = 10 - 1 # 9
in += sz * ((-5 / 9) + 1)
# += 9 * (( 0) + 1) == 9
# in == 6
return input[in] # 6
It is clear that sz = len - 1 is responsible for the behaviour you have observed. It was changed from sz = len in a suggestively named commit dating back to 2007: Fix off-by-on errors in ndimage boundary routines. Update tests.
I don't know why such change was introduced. One of the possible explanations that come to my mind is as follows:
Function 'shift' uses splines for interpolation.
A knot vector of an uniform spline on interval [0, k] is simply [0,1,2,...,k]. When we say that the spline should wrap, it is natural to require equality on values for knots 0 and k, so that many copies of the spline could be glued together, forming a periodic function:
0--1--2--3-...-k 0--1--2--3-...-k 0--1-- ...
0--1--2--3-...-k 0--1--2--3-...-k ...
Maybe shift just treats its input as a list of values for spline's knots?
It is worth noting that this behavior appears to be a bug, as noted in this SciPy issue:
https://github.com/scipy/scipy/issues/2640
The issue appears to effect every extrapolation mode in scipy.ndimage other than mode='mirror'.
I am new to sympy but I already get a nice output when I plot the implicit function (actually the formula for Cassini's ovals) using sympy:
from sympy import plot_implicit, symbols, Eq, solve
x, y = symbols('x y')
k=2.7
a=3
eq = Eq((x**2 + y**2)**2-2*a**2*(x**2-y**2), k**4-a**4)
plot_implicit(eq)
Now is it actually possible to somehow get the x and y values corresponding to the plot? or alternatively solve the implicit equation without plotting at all?
thanks! :-)
This is an answer addressing your
is it actually possible to somehow get the x and y values corresponding to the plot?
and I say "addressing" because it's not possible to get the x and y values used to draw the curves — because the curves are not drawn using a sequenc of 2D points… more on this later,
TL;DR
pli = plot_implicit(...)
series = pli[0]
data, action = series.get_points()
data = np.array([(x_int.mid, y_int.mid) for x_int, y_int in data])
Let's start with your code
from sympy import plot_implicit, symbols, Eq, solve
x, y = symbols('x y')
k=2.7
a=3
eq = Eq((x**2 + y**2)**2-2*a**2*(x**2-y**2), k**4-a**4)
and plot it, with a twist: we save the Plot object and print it
pli = plot_implicit(eq)
print(pli)
to get
Plot object containing:
[0]: Implicit equation: Eq(-18*x**2 + 18*y**2 + (x**2 + y**2)**2, -27.8559000000000) for x over (-5.0, 5.0) and y over (-5.0, 5.0)
We are interested in this object indexed by 0,
ob = pli[0]
print(dir(ob))
that gives (ellipsis are mine)
['__class__', …, get_points, …, 'var_y']
The name get_points sounds full of promise, doesn't it?
print(ob.get_points())
that gives (edited for clarity and with a big cut)
([
[interval(-3.759774, -3.750008), interval(-0.791016, -0.781250)],
[interval(-3.876961, -3.867195), interval(-0.634768, -0.625003)],
[interval(-3.837898, -3.828133), interval(-0.693361, -0.683596)],
[interval(-3.847664, -3.837898), interval(-0.673830, -0.664065)],
...
[interval(3.837895, 3.847661), interval(0.664064, 0.673830)],
[interval(3.828130, 3.837895), interval(0.683596, 0.693362)],
[interval(3.867192, 3.876958), interval(0.625001, 0.634766)],
[interval(3.750005, 3.759770), interval(0.781255, 0.791021)]
], 'fill')
What is this? the documentation of plot_implicit has
plot_implicit, by default, uses interval arithmetic to plot functions.
Following the source code of plot_implicit.py and plot,py one realizes that, in this case, the actual plotting (speaking of the matpolotlib backend) is just a line of code
self.ax.fill(x, y, facecolor=s.line_color, edgecolor='None')
where x and y are constructed from the list of intervals, as returned from .get_points(), as follows
x, y = [], []
for intervals in interval_list:
intervalx = intervals[0]
intervaly = intervals[1]
x.extend([intervalx.start, intervalx.start,
intervalx.end, intervalx.end, None])
y.extend([intervaly.start, intervaly.end,
intervaly.end, intervaly.start, None])
so that for each couple of intervals matplotlib is directed to draw a filled rectangle, small enough that the eye sees a continuous line (note the use of None to have disjoint rectangles).
We can conclude that the list of couples of intervals
l_xy_intervals = ((pli[0]).get_points())[0]
represents rectangular areas where the implicit expression you are plotting is
"true enough"
You can do this, even with interval math, if you try getting the mid point of each interval. Starting from your code, and slightly change it, by saving the plot_implicit object in a variable called g we have:
from sympy import plot_implicit, symbols, Eq, solve
x, y = symbols('x y')
k=2.7
a=3
eq = Eq((x**2 + y**2)**2-2*a**2*(x**2-y**2), k**4-a**4)
g = plot_implicit(eq)
Now let's save in a variable named ptos the intervals that were used to draw the plot.
ptos = g[0].get_points()[0]
This way ptos[0][0] will be the first interval in the x axis and ptos[0][1] will be its pair in the y axis. The intervals have a property called mid which gives the middle point of the interval. So you can suppose that ptos[0][0].mid, ptos[0][1].mid will be a pair x,y "true enough" to be one of our numerical solutions.
This way, a data frame composed of this middle point pairs can be generated with:
intervs = np.array(dtype='object')
meio = lambda x0:x0.mid
px = list(map(meio, intervs[:,0]))
py = list(map(meio, intervs[:,1]))
import pandas as pd
dados = pd.DataFrame({'x':px, 'y':px})
dados.head()
Which in this example would give us:
x y
0 -1.177733 0.598826
1 -1.175389 0.596483
2 -1.175389 0.598826
3 -1.173045 0.596483
4 -1.173045 0.598826
This idea of getting the intervals middle points can be used whenever one needs to move from "interval math" to "standard" point level math. Hope this helps. Regards.
I want to draw a Bifurcation diagram of quadratic map in python.
Basically its a plot of x_{n+1}=x_n^2-c and it should look like http://static.sewanee.edu/Physics/PHYSICS123/image99.gif
But I am newbie so I am not sure do I make it right.
My code
import numpy as n
import scipy as s
import pylab as p
xa=0.252
xb=1.99
C=n.linspace(xa,0.001,xb)
iter=100
Y=n.zeros((len(X),iteracje))
i=1
Y0=1
for Y0 in iter:
Y(i+1)=Y0^2-C
for Y0 in iter:
Y(i+1)=Y0^2-C
p.plot(C,Y)
p.show()
My problem is that I don't know how properly write these for loop properly.
Here is some modified code (partial explanation below)
import numpy as n
import scipy as s
import pylab as p
xa=0.252
xb=1.99
C=n.linspace(xa,xb,100)
print C
iter=1000
Y = n.ones(len(C))
for x in xrange(iter):
Y = Y**2 - C #get rid of early transients
for x in xrange(iter):
Y = Y**2 - C
p.plot(C,Y, '.', color = 'k', markersize = 2)
p.show()
First, the linspace command had the wrong format. help(s.linspace) will give you insight into the syntax. The first two arguments are start and stop. The third is how many values. I then made Y a numpy array of the same length as C, but whose values were all 1. Your Y0 was simply the number 1, and it never changed. Then I did some iteration to get past the initial conditions. Then did more iteration plotting each value.
To really understand what I've done, you'll have to look at how numpy handles calculations with arrays.