I have a module that I want to import. Lets say its name is module1.py .
There is a function inside this module (F(X,Y)). Here is a part of this module:
def F(X,Y):
S=complex(X,Y)
Fs=2/(pow(S,3))
Rfs=real(Fs)
return Rfs
Sum=F(X,0)/2.
print Sum
I can import this module by:
import module1
But I need to change something in the F function after I import it. For example I want to substitute this function in the module with the old one (I want to change Fs in the F function):
def F(X,Y):
S=complex(X,Y)
Fs=1/(S-1)
Rfs=real(Fs)
return Rfs
Could you please tell me how I can do that in python 2.7?
You can do this by extending Module1. Extending a class allows you to keep all of the previous functions and attributes of the base class but override any that you would like to change.
This example shows that you can call all of the other functions inside of the original Module1 but that when you call the F() function it uses the one from extended class.
Python2.7
Module1.py
class Module1():
def F(self,X,Y):
S=complex(X,Y)
Fs=2/(pow(S,3))
Rfs=real(Fs)
return Rfs
def G(self):
return "function G"
def H(self):
return "function H"
Module1_ext.py
import Module1
class Module1(Module1.Module1):
def F(self,X,Y):
return X*Y;
run.py
from Module1_ext import Module1
mod = Module1()
print(mod.G())
print(mod.H())
print(mod.F(2,3))
Python3+
Module1.py
class Module1():
def F(X,Y):
S=complex(X,Y)
Fs=2/(pow(S,3))
Rfs=real(Fs)
return Rfs
def G():
return "function G"
def H():
return "function H"
Module1_ext.py
import Module1
class Module1(Module1.Module1):
def F(X,Y):
return X*Y;
run.py
from Module1_ext import Module1
print(Module1.G())
print(Module1.H())
print(Module1.F(2,3))
Finally I figured it out by myself. This is how I solved the issue:
First we need to rewrite the module in this form:
module1.py
from numpy import *
M = 11
SU = zeros(M + 2)
C = zeros(M + 1)
C[0] = 1
for k in range(1, M + 1):
C[k] = (M - (k - 1)) * C[k - 1] / k
# T=input("TIME=")
class BB:
def F(self, fnRf):
T=1
A = 19.1
U = exp(A / 2.) / T
X = A / (2. * T)
H = pi / T
Ntr = 15
Sum = fnRf(X, 0) / 2.
for N in range(1, Ntr + 1):
Y = N * H
Sum += (-1) ** N * fnRf(X, Y)
SU[0] = Sum
for K in range(1, M + 2):
N = Ntr + K
Y = N * H
SU[K] = SU[K - 1] + (-1) ** N * fnRf(X, Y)
Avgsu = 0.
Avgsu1 = 0.
for J in range(M + 1):
Avgsu += C[J] * SU[J]
Avgsu1 += C[J] * SU[J + 1]
Fun = U * Avgsu / 2048
Fun1 = U * Avgsu1 / 2048
print Fun1
We can import this module like this:
from module1 import *
def fnRf(X, Y):
S = complex(X, Y)
Fs = 1. / (S-1)
Rfs = real(Fs)
return Rfs
ss=BB()
ss.F(fnRf)
This way we are flexible to define the function (in the module). Now it works perfectly. I hope it was helpful.
Related
from sympy import Sum, Eq
from sympy.abc import n,x
import random
def polynomial(x):
i = 0
def random_value(i):
return random.choice([i for i in range(-10,10) if i not in [0]])
eq = Sum(random_value(i)*x**n, (n,0,random_value(i)))
display(Eq(eq,eq.doit(), evaluate=False))
polynomial(x)
polynomial(x)
With this code, the coefficients are always the same.
Also, I am not sure if the algebra evaluations are correct for b < 0 .
One way is to use IndexedBase to generate symbolic-placeholder coefficients, and then substitute them with numerical coefficients.
from sympy import Sum, Eq, Matrix, IndexedBase
from sympy.abc import n, x
import random
def polynomial(x):
# n will go from zero to this positive value
to = random.randint(0, 10)
# generate random coefficients
# It is important for them to be a sympy Matrix or Tuple,
# otherwise the substitution (later step) won't work
coeff = Matrix([random.randint(-10, 10) for i in range(to + 1)])
c = IndexedBase("c")
eq = Sum(c[n]*x**n, (n, 0, to)).doit()
eq = eq.subs(c, coeff)
return eq
display(polynomial(x))
display(polynomial(x))
Another ways is to avoid using Sum, relying instead on list-comprehension syntax and builtin sum:
def polynomial(x):
to = random.randint(0, 10)
coeff = [random.randint(-10, 10) for i in range(to + 1)]
return sum([c * x**n for c, n in zip(coeff, range(to + 1))])
display(polynomial(x))
display(polynomial(x))
You can pass a list of coefficients (with highest order coefficient first and constant last) directly to Poly and then convert that to an expression:
>>> from sympy import Poly
>>> from sympy.abc import x
>>> Poly([1,2,3,4], x)
Poly(x**3 + 2*x**2 + 3*x + 4, x, domain='ZZ')
>>> _.as_expr()
x**3 + 2*x**2 + 3*x + 4
>>> from random import randint, choice
>>> Poly([choice((-1,1))*randint(1,10) for i in range(randint(0, 10))], x).as_expr()
-3*x**4 + 3*x**3 - x**2 - 6*x + 2
When creating a sympy vector, first I create the coordinate system, for example for cylindrical coordinates:
from sympy.vector import CoordSys3D
from IPython.display import display
R = CoordSys3D('', transformation='cylindrical', variable_names=("r", "theta", "z"),vector_names=('i', 'j', 'k'))
I want to change the latex names of variables and vectors. As I searched, the CoordSys3D has those inputs:
class sympy.vector.coordsysrect.CoordSys3D(name, transformation=None, parent=None, location=None, rotation_matrix=None, vector_names=None, variable_names=None)[source]
if I print R.theta with:
display(R.theta)
I get $theta$, but i would like to have $\theta$
However, inside its __init__, there are the latex_scalars and latex_vects
__init__(name, location=None, rotation_matrix=None, parent=None, vector_names=None, variable_names=None, latex_vects=None, pretty_vects=None, latex_scalars=None, pretty_scalars=None, transformation=None)
Can I give a value to it?
I was having the same problem, and I found an answer.
R = CoordSys3D('R', transformation='cylindrical', variable_names=("r", "theta", "z"),vector_names=('i', 'j', 'k'))
R.theta._latex_form = '\\theta'
R.j._latex_form = '\\vectorunit{\\theta}'
The ._latex_form attribute also works the same way when you define a sympy function:
E_phi = smp.Function('E_phi')()
E_phi._latex_form = 'E_{\\phi}'
However, there is no ._latex_form attribute for symbols. But I found another way to do it:
E_phi = Symbol('E_{\\phi}')
Remember to use double backslash when entering latex code in python.
Here is some example code I wrote. The output is formatted for MathJax. The output looks like this:
$$ \require{physics} $$
$$ \vb{E} = (E_{r})\vectorunit{r} + (7 e^{i \omega t})\vectorunit{\phi} + (E_{z})\vectorunit{z} $$
$$ \curl{\vb{E}} = (\frac{7 e^{i \omega t}}{r})\vectorunit{z} $$
$$ \vb{B} = (\begin{cases} \frac{7 i e^{i \omega t}}{r \omega} & \text{for}\: r \omega \neq 0 \\- \frac{7 t}{r} & \text{otherwise} \end{cases})\vectorunit{z} $$
import numpy as np
import sympy as smp
import matplotlib.pyplot as plt
from sympy import *
from sympy import symbols
from sympy.vector import divergence
from sympy.vector import curl
from sympy.vector import gradient
from sympy import diff
from sympy import exp
from sympy import integrate
from sympy import I, pi
from sympy.vector import CoordSys3D
N = CoordSys3D('N', transformation='cylindrical',
vector_names=("r", "phi", "z"),
variable_names=("R", "PHI", "Z"))
# Variables
R = N.R
PHI = N.PHI
Z = N.Z
R._latex_form = 'r'
PHI._latex_form = '\\phi'
Z._latex_form = 'z'
# Basis Unit Vectors
rhat = N.r
phihat = N.phi
zhat = N.z
rhat._latex_form = '\\vectorunit{r}'
phihat._latex_form = '\\vectorunit{\\phi}'
zhat._latex_form = '\\vectorunit{z}'
# The r, phi, and z components of the Electric Field
E_r = Symbol('E_{r}')
E_phi = Symbol('E_{\\phi}')
E_z = Symbol('E_{z}')
# Symbols
x, y, z, t = symbols('x y z t')
wavenumber = symbols('k')
E_0 = symbols('E_0') # Amplitude of E field
w = symbols('omega' , real=True, positive=True)
# Define E_phi(r,phi,z,t)
# Note: I = sqrt(-1)
# E_phi = (1/R) * smp.exp( I * ( w*t ))
E_phi = 7 * smp.exp( I * w * t)
# The Electric Field
E = (E_r * rhat) + (E_phi * phihat) + (E_z * zhat)
# Compute B by integrating the curl of E wrt time
# curl E = - dB/dt
# integrate( (curl E) , t ) = - B
jimmy = curl( E )
B = -integrate( jimmy, t )
# Display the answers as LATEX
# init_printing(use_unicode=True, wrap_line=False)
init_printing( use_latex='mathjax' )
print("$$ \\require{physics} $$")
print("$$ \\vb{E} = " + latex(E) + " $$")
print("$$ \\curl{\\vb{E}} = " + latex(jimmy) + " $$")
print("$$ \\vb{B} = " + latex(B.simplify()) + " $$")
# Alternative Way of defining the components of
# the Electric Field:
# The r, phi, and z components of the Electric Field
# E_r = smp.Function('E_r')()
# E_phi = smp.Function('E_phi')()
# E_z = smp.Function('E_z')()
# E_r._latex_form = 'E_{r}'
# E_phi._latex_form = 'E_{\\phi}'
# E_z._latex_form = 'E_{z}'
# Note that if we define these variables as symbols()
# Then we have to give the latex form this way:
# E_phi = symbol('E_{\\phi}')
# symbols have no attribute ._latex_form
# Whereas Functions do.
Thank you in advance and sorry for the bad english!
FullScript.py
from sympy import *
var('n')
f= 3**n/3
print(simplify(f))
#---------------------
f= 2*3**n/3
print(simplify(f))
# 3**(n - 1) # OK
# 2*3**n/3 # I want 2*3**(n-1)
2018-11-27------------------------------
Please tell me how to use the if statement
How to extract numerator and denominator from polynomial without evaluating?
FullScript.py
from sympy import *
var('n')
def MySimplify(h):
Mypoly = poly(h)
aa = Mypoly.all_coeffs()[1]
bb = h - aa
n, d = fraction(bb)
nn0 = n.as_base_exp()[0]
nn1 = poly(nn0)
import re
rese1 = re.search('^Poly\((.+?),(.+?),', str(nn1)).group(1)
rese2 = re.search('^Poly\((.+?),(.+?),', str(nn1)).group(2)
two=sympify(rese1)/sympify(rese2)
ans = powsimp(bb/two)*two+aa
return ans
f= 3**n/3
print("f1=",f)
print("f2=",simplify(f))
g= 4+2*3**n/3
print("g1=",g)
print("g2=",simplify(g))
print("g3=",MySimplify(g))
# f1= 3**n/3
# f2= 3**(n - 1)
# g1= 2*3**n/3 + 4
# g2= 2*3**n/3 + 4
# g3= 2*3**(n - 1) + 4
2018-11-28------------------------------
FullScript.py
from sympy import *
var('m n p q r s t u v x')
def ps(e, *args):
x = Dummy(integer=True)
t=list(Add.make_args(e))
for i, ti in enumerate(t):
c, r = ti.as_coeff_Mul()
if c.is_Rational and not c.is_Integer:
t[i] = Mul(c.p, r, Pow(c.q, x), evaluate=False)
# t[i] = powersimp(t[i], *args).xreplace({x: -1})
t[i] = powsimp(t[i], *args).xreplace({x: -1})
else:
t[i] = powsimp(t[i], *args)
return Add(*t)
f= 4+2*3**n/3
print("f1=",f)
print("f1=",ps(f))
f= 4+2*3**n/3+5*2.4**(m-1)/2.4+6*5.6*(p-7)/8.9
print("f2=",f)
print("f2=",ps(f))
g= x+p**n/p
print("g1=",g)
print("g1=",ps(g))
g= x+p**n/p+q*s**(m-1)/s+r*t**(u-2)/v
print("g2=",g)
print("g2=",ps(g))
# f1= 2*3**n/3 + 4
# f1= 2*3**(n - 1) + 4
# f2= 2.08333333333333*2.4**(m - 1) + 2*3**n/3 + 3.7752808988764*p - 22.4269662921348
# f2= 2.08333333333333*2.4**(m - 1) + 2*3**(n - 1) + 3.7752808988764*p - 22.4269662921348
# g1= x + p**n/p
# g1= p**(n - 1) + x
# g2= q*s**(m - 1)/s + r*t**(u - 2)/v + x + p**n/p
# g2= p**(n - 1) + q*s**(m - 2) + r*t**(u - 2)/v + x
powsimp(f/2)*2 will do what you want. The following is a more general workaround that incorporates this idea:
def ps(e, *args):
x = Dummy(integer=True)
t=list(Add.make_args(e))
for i, ti in enumerate(t):
c, r = ti.as_coeff_Mul()
if c.is_Rational and not c.is_Integer:
t[i] = Mul(c.p, r, Pow(c.q, x), evaluate=False)
t[i] = powersimp(t[i], *args).xreplace({x: -1})
else:
t[i] = powsimp(t[i], *args)
return Add(*t)
I need a function in python to return N random numbers from a skew normal distribution. The skew needs to be taken as a parameter.
e.g. my current use is
x = numpy.random.randn(1000)
and the ideal function would be e.g.
x = randn_skew(1000, skew=0.7)
Solution needs to conform with: python version 2.7, numpy v.1.9
A similar answer is here: skew normal distribution in scipy However this generates a PDF not the random numbers.
I start by generating the PDF curves for reference:
NUM_SAMPLES = 100000
SKEW_PARAMS = [-3, 0]
def skew_norm_pdf(x,e=0,w=1,a=0):
# adapated from:
# http://stackoverflow.com/questions/5884768/skew-normal-distribution-in-scipy
t = (x-e) / w
return 2.0 * w * stats.norm.pdf(t) * stats.norm.cdf(a*t)
# generate the skew normal PDF for reference:
location = 0.0
scale = 1.0
x = np.linspace(-5,5,100)
plt.subplots(figsize=(12,4))
for alpha_skew in SKEW_PARAMS:
p = skew_norm_pdf(x,location,scale,alpha_skew)
# n.b. note that alpha is a parameter that controls skew, but the 'skewness'
# as measured will be different. see the wikipedia page:
# https://en.wikipedia.org/wiki/Skew_normal_distribution
plt.plot(x,p)
Next I found a VB implementation of sampling random numbers from the skew normal distribution and converted it to python:
# literal adaption from:
# http://stackoverflow.com/questions/4643285/how-to-generate-random-numbers-that-follow-skew-normal-distribution-in-matlab
# original at:
# http://www.ozgrid.com/forum/showthread.php?t=108175
def rand_skew_norm(fAlpha, fLocation, fScale):
sigma = fAlpha / np.sqrt(1.0 + fAlpha**2)
afRN = np.random.randn(2)
u0 = afRN[0]
v = afRN[1]
u1 = sigma*u0 + np.sqrt(1.0 -sigma**2) * v
if u0 >= 0:
return u1*fScale + fLocation
return (-u1)*fScale + fLocation
def randn_skew(N, skew=0.0):
return [rand_skew_norm(skew, 0, 1) for x in range(N)]
# lets check they at least visually match the PDF:
plt.subplots(figsize=(12,4))
for alpha_skew in SKEW_PARAMS:
p = randn_skew(NUM_SAMPLES, alpha_skew)
sns.distplot(p)
And then wrote a quick version which (without extensive testing) appears to be correct:
def randn_skew_fast(N, alpha=0.0, loc=0.0, scale=1.0):
sigma = alpha / np.sqrt(1.0 + alpha**2)
u0 = np.random.randn(N)
v = np.random.randn(N)
u1 = (sigma*u0 + np.sqrt(1.0 - sigma**2)*v) * scale
u1[u0 < 0] *= -1
u1 = u1 + loc
return u1
# lets check again
plt.subplots(figsize=(12,4))
for alpha_skew in SKEW_PARAMS:
p = randn_skew_fast(NUM_SAMPLES, alpha_skew)
sns.distplot(p)
from scipy.stats import skewnorm
a=10
data= skewnorm.rvs(a, size=1000)
Here, a is a parameter which you can refer to:
https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.skewnorm.html
Adapted from rsnorm function from fGarch R package
def random_snorm(n, mean = 0, sd = 1, xi = 1.5):
def random_snorm_aux(n, xi):
weight = xi/(xi + 1/xi)
z = numpy.random.uniform(-weight,1-weight,n)
xi_ = xi**numpy.sign(z)
random = -numpy.absolute(numpy.random.normal(0,1,n))/xi_ * numpy.sign(z)
m1 = 2/numpy.sqrt(2 * numpy.pi)
mu = m1 * (xi - 1/xi)
sigma = numpy.sqrt((1 - m1**2) * (xi**2 + 1/xi**2) + 2 * m1**2 - 1)
return (random - mu)/sigma
return random_snorm_aux(n, xi) * sd + mean
I have an elliptic curve plotted. I want to draw a line along a P,Q,R (where P and Q will be determined independent of this question). The main problem with the P is that sympy solve() returns another equation and it needs to instead return a value so it can be used to plot the x-value for P. As I understood it, solve() should return a value, so I'm clearly doing something wrong here that I'm just totally not seeing. For reference, here's how P+Q=R should look:
I've been going over the docs and other material and this is as far as I've been able to get myself into trouble:
from mpl_toolkits.axes_grid.axislines import SubplotZero
from pylab import *
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.path import Path
import matplotlib.patches as patches
from matplotlib import rc
import random
from sympy.solvers import solve
from sympy import *
def plotGraph():
fig = plt.figure(1)
#ax = SubplotZero(fig, 111)
#fig.add_subplot(ax)
#for direction in ["xzero", "yzero"]:
#ax.axis[direction].set_axisline_style("-|>")
#ax.axis[direction].set_visible(True)
#ax.axis([-10,10,-10,10])
a = -2; b = 1
y, x = np.ogrid[-10:10:100j, -10:10:100j]
xlist = x.ravel(); ylist = y.ravel()
elliptic_curve = pow(y, 2) - pow(x, 3) - x * a - b
plt.contour(xlist, ylist, elliptic_curve, [0])
#rand = random.uniform(-5,5)
randmid = random.randint(30,70)
#y = ylist[randmid]; x = xlist[randmid]
xsym, ysym = symbols('x ylist[randmid]')
x_result = solve(pow(ysym, 2) - pow(xsym, 3) - xsym * a - b, xsym) # 11/5/13 needs to return a value
plt.plot([-1.5,5], [-1,8], color = "c", linewidth=1) # plot([x1,x2,x3,...],[y1,y2,y3,...])
plt.plot([xlist[randmid],5], [ylist[randmid],8], color = "m", linewidth=1)
#rc('text', usetex=True)
text(-9,6,' size of xlist: %s \n size of ylist: %s \n x_coord: %s \n random_y: %s'
%(len(xlist),len(ylist),x_result,ylist[randmid]),
fontsize=10, color = 'blue',bbox=dict(facecolor='tan', alpha=0.5))
plt.annotate('$P+Q=R$', xy=(2, 1), xytext=(3, 1.5),arrowprops=dict(facecolor='black', shrink=0.05))
## verts = [(-5, -10),(5, 10)] # [(x,y)startpoint,(x,y)endpoint] #,(0, 0)]
## codes = [Path.MOVETO,Path.LINETO] # related to verts[] #,Path.STOP]
## path = Path(verts, codes)
## patch = patches.PathPatch(path, facecolor='none', lw=2)
## ax.add_patch(patch)
plt.grid(True)
plt.show()
def main():
plotGraph()
if __name__ == '__main__':
main()
Ultimately, I'd like to draw a line to show P+Q=R, so if someone also has something to add on how to code to get the Q that would be greatly appreciated. I'm teaching myself about Python and elliptic curves so I'm sure that any entry-level programmer can figure out in 2 minutes what I've been on for some time already.
I don't know what are you calculating, but here is the code that can plot the graph:
import numpy as np
import pylab as pl
Y, X = np.mgrid[-10:10:100j, -10:10:100j]
def f(x):
return x**3 -3*x + 5
px = -2.0
py = -np.sqrt(f(px))
qx = 0.5
qy = np.sqrt(f(qx))
k = (qy - py)/(qx - px)
b = -px*k + py
poly = np.poly1d([-1, k**2, 2*k*b+3, b**2-5])
x = np.roots(poly)
y = np.sqrt(f(x))
pl.contour(X, Y, Y**2 - f(X), levels=[0])
pl.plot(x, y, "o")
pl.plot(x, -y, "o")
x = np.linspace(-5, 5)
pl.plot(x, k*x+b)
graph:
based on HYRY's answer, I just update some details to make it better:
import numpy as np
import pylab as pl
Y, X = np.mgrid[-10:10:100j, -10:10:100j]
def f(x, a, b):
return x**3 + a*x + b
a = -2
b = 4
# the 1st point: 0, -2
x1 = 0
y1 = -np.sqrt(f(x1, a, b))
print(x1, y1)
# the second point
x2 = 3
y2 = np.sqrt(f(x2, a, b))
print(x2, y2)
# line: y=kl*x+bl
kl = (y2 - y1)/(x2 - x1)
bl = -x1*kl + y1 # bl = -x2*kl + y2
# y^2=x^3+ax+b , y=kl*x+bl => [-1, kl^2, 2*kl*bl, bl^2-b]
poly = np.poly1d([-1, kl**2, 2*kl*bl-a, bl**2-b])
# the roots of the poly
x = np.roots(poly)
y = np.sqrt(f(x, a, b))
print(x, y)
pl.contour(X, Y, Y**2 - f(X, a, b), levels=[0])
pl.plot(x, y, "o")
pl.plot(x, -y, "o")
x = np.linspace(-5, 5)
pl.plot(x, kl*x+bl)
And we got the roots of this poly:
[3. 2.44444444 0. ] [5. 3.7037037 2. ]