Function with a choice of parameters used - python

I have a two functions where I set parameters for mathematical function. I would like to create one if possible where I would type:
x, y = one_demo_fun(a=1,
b=2,
c=5,
power_of_the_first_x=2,
power_of_the_second_x=1))
or
x, y = one_demo_fun(y = 1 * (x ** 2) + (2 * x) + 5)
and get the same result.
I have two functions which I would like to make one, where user can type one of above:
def function_demo_parameters( # type function settings ax^2+bx+c
a=1,
b=1,
c=1,
power_of_the_first_x=2,
power_of_the_second_x=1):
x = np.linspace(-2, 2, 100)
y = a * (x ** power_of_the_first_x) + b * (x ** power_of_the_second_x) + c
return x, y
def function_demo_equation( # type function
y=1 * (x ** 2) + (2 * x) + 5):
x = np.linspace(-2, 2, 100)
y = y
return x, y
x, y = function_demo_parameters()
x_1, y_1 = function_demo_equation()
Is there some way to merge them or other way to look at the problem?

You don't want an equation; you want the function that the equation implies.
function_demo_equation(lambda x: 1*(x**2) + 2*x + 5)

Related

How do I solve expressions in python such as f1(x) = f2(x)?

import math
import pylab
import sympy
def f1(x):
"""function representing a cosine variant function and returned"""
return math.cos(2 * math.pi * x) * math.exp(-x ** 2)
def f2(x):
"""function representing a log variant function and returned"""
return math.log(x + 2.2)
def positive_places(f, xs):
"""return a list of elements of xs that are positive when operated in by
f"""
list1 = []
for i in xs:
if f(i) > 0:
list1.append(i)
return list1
def create_plot_data(f, xmin, xmax, n):
"""returns a tuple (xs, ys) where xs and ys are two sequences,
each containing n numbers"""
xs = [xmin + i * ((xmax - xmin) / (n - 1)) for i in range(n)]
ys = [f(xs[i]) for i in range(n)]
return (xs, ys)
def myplot():
"""plots a graph of f1() and returns the graph"""
print(create_plot_data(f1, -2, 2, 1001))
(a1, b1) = create_plot_data(f1, -2, 2, 1001)
(a2, b2) = create_plot_data(f2, -2, 2, 1001)
pylab.plot(a1, b1, label='f1(x)')
pylab.plot(a2, b2, label='f2(x)')
pylab.xlabel('x')
pylab.ylabel('y')
pylab.legend()
pylab.grid()
pylab.savefig('plot.pdf')
pylab.savefig('plot.png')
pylab.show()
def find_cross():
return sympy.solve(math.cos(2 * math.pi * x) * math.exp(-x ** 2) - math.log(x + 2.2), x)
`
Hi im trying to define a function that will find the positive x value point where 2 equations are equal: f1(x) = f2(x)
f1(x) = math.cos(2 * math.pi * x) * math.e ** (-x ** 2)
f2(x) = math.log(x + 2.2)
for the point between x = 0 and x = 0.5
When using SymPy you can take advantage of mpmath's root finder ability to work with arbitrary many digits:
import mpmath
import sympy as sy
sy.init_printing()
mpmath.mp.dps = 30 # accuracy of 30 digits
# declare expressions:
x = sy.Symbol('x', real=True)
f1 = sy.cos(2*sy.pi*x) * sy.exp(-x**2)
f2 = sy.log(x + sy.Rational(22, 10))
g = f2 - f1 # f1 == f2 is equivalent to g == 0:
dg = g.diff(x) # 1. derivative needed by numeric root-finder
# generate numeric functions from SymPy expressions:
g_m, dg_m = (sy.lambdify(x, f_, modules="mpmath") for f_ in (g, dg))
# find the roots:
x_sln = mpmath.findroot(g_m, [0, 0.5], solver='secant', df=dg)
print("Intersection f1(x) == f2(x) is at x = {}".format(x_sln))
# => Intersection f1(x) == f2(x) is at x = 0.0922612383093564032487110560683
Note that mixing SymPy, math (and NumPy) functions can have unwanted side effects.

How To Find Complex Roots of A Multivariate Polynomial Equation System (Python)

Consider following equation system:
1623.66790917 * x ** 2 + 468.829686367 * x * y + 252.762128419 * y ** 2 + -1027209.42116 * x + -301192.975791 * y + 188804356.212 = 0
11154.1759415 * x ** 2 + 31741.0229155 * x * y + 32933.5622632 * y ** 2 + -16226174.4037 * x + -26323622.7497 * y + 6038609721.67 = 0
As you see there are two pairs of complex solutions to the system. I tried sympy but it was not a success. I want to know how to figure it out in Python. BTW I don't have a nice initial guess to use numeric methods.
You can solve those equations numerically using mpmath's findroot(). As far as I know there isn't a way to tell findroot() to find multiple roots, but we can get around that restriction: first, find a solution pair (xa, ya), then divide the equations by (x - xa)*(y - ya). You do have to supply an initial approximate solution, but I managed to find something that worked in only a few tries.
from mpmath import mp
mp.dps = 30
prec = 20
f_1 = lambda x, y: 1623.66790917 * x ** 2 + 468.829686367 * x * y + 252.762128419 * y ** 2 + -1027209.42116 * x + -301192.975791 * y + 188804356.212
f_2 = lambda x, y: 11154.1759415 * x ** 2 + 31741.0229155 * x * y + 32933.5622632 * y ** 2 + -16226174.4037 * x + -26323622.7497 * y + 6038609721.67
def solve(f1, f2, initxy):
return mp.findroot([f1, f2], initxy, solver='muller')
def show(x, y):
print 'x=', mp.nstr(x, prec)
print 'y=', mp.nstr(y, prec)
print mp.nstr(f_1(x, y), prec)
print mp.nstr(f_2(x, y), prec)
print
f1a = f_1
f2a = f_2
xa, ya = solve(f1a, f2a, (240+40j, 265-85j))
show(xa, ya)
f1b = lambda x, y: f1a(x, y) / ((x - xa) * (y - ya))
f2b = lambda x, y: f2a(x, y) / ((x - xa) * (y - ya))
xb, yb = solve(f1b, f2b, (290+20j, 270+30j))
show(xb, yb)
output
x= (246.82064795986653023 + 42.076841530787279711j)
y= (261.83565021239842638 - 81.555049135736951496j)
(0.0 + 3.3087224502121106995e-24j)
(0.0 + 0.0j)
x= (289.31873055121622967 + 20.548128321524345062j)
y= (272.23440694481666637 + 29.381152413744722108j)
(0.0 + 3.3087224502121106995e-24j)
(0.0 + 0.0j)

A bijective function from N*N*N to N

Can anyone help me in finding a bijective mathematical function from N * N * N → N that takes three parameters x, y, and z and returns a number n?
I would like to know the function f and its inverse f' in a way that if I have n I will be able to determine x, y, z by applying f'(n).
Defining f as a composition of a simpler function g
Suppose g is a bijection from N × N to N and let g-1 be its inverse. Then we can define f in terms of g as follows.
f(x, y, z) = g(g(x, y), z) = n
f-1(n) = (x, y, z) where g-1(n) = (w, z) and g-1(w) = (x, y)
Defining g as a bijection from N × N to N
We now have the much simpler problem of defining g.
g(x, y) = (x + y)(x + y + 1) / 2 + y = n
g-1(n) = (x, y) where m = ⌊(2n)1/2⌋ and exactly one of the following two conditions hold.
x + y = m and y = n - m(m + 1) / 2
x + y = m - 1 and y = n - m(m - 1) / 2
Python implementation
def f(x, y, z):
return g(g(x, y), z)
def f_inv(n):
w, z = g_inv(n)
x, y = g_inv(w)
return (x, y, z)
def g(x, y):
return (x + y) * (x + y + 1) / 2 + y
def g_inv(n):
m = math.floor(math.sqrt(2 * n))
while True:
y = n - m * (m + 1) / 2
if y >= 0:
break
m -= 1
x = m - y
return x, y
your function is not surjective, let p is a prime number, we can't find any x,y,z in N such that p=2^x3^y5^z...
F(x,y,z) = 2^x*3^y*5^z
In fact you can choose any distinct set of prime numbers. And inverse is simply by factorizing to corresponding prime factors.

how do I make a numpy.piecewise function of arbitrary length? (having lambda issues)

I'm trying to plot a piecewise fit to my data, but I need to do it with an arbitrary number of line segments. Sometimes there are three segments; sometimes there are two. I'm storing the coefficients of the fit in actable and the bounds on the segments in btable.
Here are example values of my bounds:
btable = [[0.00499999989, 0.0244274978], [0.0244275965, 0.0599999987]]
Here are example values of my coefficients:
actable = [[0.0108687987, -0.673182865, 14.6420775], [0.00410866373, -0.0588355861, 1.07750032]]
Here's what my code looks like:
rfig = plt.figure()
<>various other plot specifications<>
x = np.arange(0.005, 0.06, 0.0001)
y = np.piecewise(x, [(x >= btable[i][0]) & (x <= btable[i][1]) for i in range(len(btable))], [lambda x=x: np.log10(actable[j][0] + actable[j][2] * x + actable[j][2] * x**2) for j in list(range(len(actable)))])
plt.plot(x, y)
The problem is that lambda sets itself to the last instance of the list, so it uses the coefficients for the last segment for all the segments. I don't know how to do a piecewise function without using lambda.
Currently, I'm cheating by doing this:
if len(btable) == 2:
y = np.piecewise(x, [(x >= btable[i][0]) & (x <= btable[i][1]) for i in range(len(btable))], [lambda x: np.log10(actable[0][0] + actable[0][1] * x + actable[0][2] * x**2), lambda x: np.log10(actable[1][0] + actable[1][1] * x + actable[1][2] * x**2)])
else if len(btable) == 3:
y = np.piecewise(x, [(x >= btable[i][0]) & (x <= btable[i][1]) for i in range(len(btable))], [lambda x: np.log10(actable[0][0] + actable[0][1] * x + actable[0][2] * x**2), lambda x: np.log10(actable[1][0] + actable[1][1] * x + actable[1][2] * x**2), lambda x: np.log10(actable[2][0] + actable[2][1] * x + actable[2][2] * x**2)])
else
print('Oh no! You have fewer than 2 or more than 3 segments!')
But this makes me feel icky on the inside. I know there must be a better solution. Can someone help?
This issue is common enough that Python's official documentation has an article Why do lambdas defined in a loop with different values all return the same result? with a suggested solution: create a local variable to be initialized by the loop variable, to capture the changing values of the latter within the function.
That is, in the definition of y it suffices to replace
[lambda x=x: np.log10(actable[j][0] + actable[j][1] * x + actable[j][2] * x**2) for j in range(len(actable))]
by
[lambda x=x, k=j: np.log10(actable[k][0] + actable[k][1] * x + actable[k][2] * x**2) for j in range(len(actable))]
By the way, one can use one-sided inequalities to specify ranges for numpy.piecewise: the last of the conditions that evaluate to True will trigger the corresponding function. (This is a somewhat counterintuitive priority; using the first true condition would be more natural, like SymPy does). If the breakpoints are arranged in increasing order, then one should use "x>=" inequalities:
breaks = np.arange(0, 10) # breakpoints
coeff = np.arange(0, 20, 2) # coefficients to use
x = np.arange(0, 10, 0.1)
y = np.piecewise(x, [x >= b for b in breaks], [lambda x=x, a=c: a*x for c in coeff])
Here each coefficient will be used for the interval that begins with the corresponding breakpoint; e.g., coefficient c=0 is used in the range 0<=x<1, coefficient c=2 in the range 1<=x<2, and so on.

What is this piece of Python code doing?

This following is a snippet of Python code I found that solves a mathematical problem. What exactly is it doing? I wasn't too sure what to Google for.
x, y = x + 3 * y, 4 * x + 1 * y
Is this a special Python syntax?
x, y = x + 3 * y, 4 * x + 1 * y
is the equivalent of:
x = x + 3 * y
y = 4 * x + 1 * y
EXCEPT that it uses the original values for x and y in both calculations - because the new values for x and y aren't assigned until both calculations are complete.
The generic form is:
x,y = a,b
where a and b are expressions the values of which get assigned to x and y respectively. You can actually assign any tuple (set of comma-separated values) to any tuple of variables of the same size - for instance,
x,y,z = a,b,c
would also work, but
w,x,y,z = a,b,c
would not because the number of values in the right-hand tuple doesn't match the number of variables in the left-hand tuple.
It's an assignment to a tuple, also called sequence unpacking. Probably it's clearer when you add parenthesis around the tuples:
(x, y) = (x + 3 * y, 4 * x + 1 * y)
The value x + 3 * y is assigned to x and the value 4 * x + 1 * y is assigned to y.
It is equivalent to this:
x_new = x + 3 * y
y_new = 4 * x + 1 * y
x = x_new
y = y_new
I also recently saw this referred to as "simultaneous assignment", which seems to capture the spirit of several of the answers.

Categories