sympy - Composition of functions and operators - python

Let's assume that we have a function f and an operator L. In this case, it can be something simple, like,
L[f](x)=\sum_{k=1}^{4}f(x+k)
My main objective is to compute compositions of operators, like L above, using sympy. Sympy has no problem handling compositions of functions but we can quickly see that there is gonna be a problem with the operator above.
For example, I can define it as,
class L(Function):
#classmethod
def eval(cls, f,x):
k = Symbol('k')
return summation(f(k+x),(k,1,4))
And this indeed computes L[f] but returns an evaluated object that is no longer a function of x, so computing L[L[f]] no longer makes sense.
Is there a way in sympy to convert what L returns to be a function of x? I think that would solve the problem, since then I would be able to re-apply L on the new object.
Thanks for your time.

This question had a simple answer after all. Sympy's Lambda does the trick in this case and then I can re-apply L after evaluation is done.

Related

Sympy: reducing custom function as string with sympify?

Is there a solution to sympify() strings including custom methods?
Sympy has the beautiful function sympify.
It can reduce strings to sympy-functions and reduce all expressions. Nice!
It allows to add 'sympify'-able functions as class.
This is the official example.
from sympy import Matrix, sympify
class MyList1(object):
def __iter__(self):
yield 1
yield 2
return
def __getitem__(self, i): return list(self)[i]
def _sympy_(self): return Matrix(self)
local_dict= {"MyList1": MyList1}
print(sympify(MyList1())) # Matrix([[1], [2]])
print(sympify('MyList1()')) # MyList1()
print(sympify('MyList1()', locals=local_dict)) # <__main__.MyList1 object at 0x0000000006D0AA20>
The last two lines can not be reduced by sympify- our class is obviously not known when sympifying a string. Putting the class into 'locals' did not work for me.
Is there a solution to reduce strings?
Need sympy function for log2(x) capable of being used in sympy.solve did not work for me
SymPy: Safely parsing strings was not solved
Also: In https://stackoverflow.com/a/58487317/5626139, the class type was id Function and not Object. Which one to use?
I think it did what you wanted...MyList1 doesn't have a method for printing but the data is there:
>>> list(sympify('MyList1()', locals=local_dict))
[1, 2]
I would consider this to be a bug in SymPy. Basically, it isn't calling _sympy_ when it constructs an object from a string. You can work around it by either calling sympify() twice, like sympify(sympify('MyList1()', locals=local_dict)). Under normal operation sympify() should be idempotent so there is no harm in doing this.

How to check if a SymPy expression has analytical integral

I want to solve my other question here so I need sympy to return an error whenever there is no analytical/symbolic solution for and integral.
For example if I try :
from sympy import *
init_printing(use_unicode=False, wrap_line=False, no_global=True)
x = Symbol('x')
integrate(1/cos(x**2), x)
It just [pretty] prints the integral itself
without solving and/or giving an error about not being able to solve it!
P.S. I have also asked this question here on Reddit.
A "symbolic" solution always exists: I just invented a new function intcos(x), which by definition is the antiderivative of 1/cos(x**2). Now this integral has a symbolic solution!
For the question to be rigorously answerable, one has to restrict the class of functions allowed in the answer. Typically one considers elementary functions. As SymPy integral reference explains, the Risch algorithm it employs can prove that some functions do not have elementary antiderivatives. Use the option risch=True and check whether the return value is an instance of sympy.integrals.risch.NonElementaryIntegral
from sympy.integrals.risch import NonElementaryIntegral
isinstance(integrate(1/exp(x**2), x, risch=True), NonElementaryIntegral) # True
However, since Risch algorithm implementation is incomplete, in many cases like 1/cos(x**2) it returns an ordinary Integral object. This means it was not able to either find an elementary antiderivative or prove that one does not exist.
For this example, it helps to rewrite the trigonometric function in terms of exponential, with rewrite(cos, exp):
isinstance(integrate((1/cos(x**2)).rewrite(cos, exp), x, risch=True), NonElementaryIntegral)
returns True, so we know the integral is nonelementary.
Non-elementary antiderivatives
But often we don't really need an elementary function; something like Gamma or erf or Bessel functions may be okay; as long as it's some "known" function (which of course is a fuzzy term). The question becomes: how to tell if SymPy was able to integrate a specific expression or not? Use .has(Integral) check for that:
integrate(2/cos(x**2), x).has(Integral) # True
(not isinstance(Integral) because the return value can be, like here, 2*Integral(1/cos(x**2), x).) This does not prove anything other than SymPy's failure to find the antiderivative. The antiderivative may well be a known function, even an elementary one.

Python: How do i find an equation's value for a given input

Say, I have an equation f(x) = x**2 + 1, I need to find the value of f(2).
Easiest way is to create a function, accept a parameter and return the value.
But the problem is, f(x) is created dynamically and so, a function cannot be written beforehand to get the value.
I am using cvxpy for an optimization value. The equation would look something like below:
x = cvx.Variable()
Si = [(cvx.square(prev[i] + cvx.sqrt(200 - cvx.square(x))) for i in range(3)]
prev is an array of numbers. There will be a Si[0] Si[1] Si[2].
How do i find the value of Si[0] for x=20?
Basically, Is there any way to substitue the said Variable and find the value of equation When using cvxpy ?
Set the value of the variables and then you can obtain the value of the expression, like so:
>>> x.value = 3
>>> Si[0].value
250.281099844341
(although it won't work for x = 20 because then you'd be taking the square root of a negative number).
The general solution to interpreting code on-the-fly in Python is to use the built-in eval() but eval is dangerous with user-supplied input which could do all sorts of nasty to your system.
Fortunately, there are ways to "sandbox" eval using its additional parameters to only give the expression access to known "safe" operations. There is an example of how to limit access of eval to only white-listed operations and specifically deny it access to the built-ins. A quick look at that implementation looks close to correct, but I won't claim it is foolproof.
The sympy.sympify I mentioned in my comment uses eval() inside and carries the same warning.
In parallel to your cvx versions, you can use lambda to define functions on the fly :
f=[lambda x,i=j : (prev[i] + (200 - x*x)**.5)**2 for j in range(3)] #(*)
Then you can evaluate f[0](20), f[1](20), and so on.
(*) the i=j is needed to fit each j in the associated function.

Python standard function for dual of map

Does the Python language have a built-in function for an analog of map that sends an argument to a sequence of functions, rather than a function to a sequence of arguments?
Plain map would have "type" (thinking like Haskell) (a -> b) -> [a] -> [b]; is there anything with the corresponding type a -> [(a -> b)] -> [b]?
I could implement this in a number of ways. Here's using a lambda
def rev_map(x, seq):
evaluate_yourself_at_x = lambda f: f(x)
return map(evaluate_yourself_at_x, seq)
rev_map([1,2], [sum, len, type])
which prints [3, 2, list].
I'm just curious if this concept of "induce a function to evaluate itself at me" has a built-in or commonly used form.
One motivation for me is thinking about dual spaces in functional analysis, where a space of elements which used to be conceived of as arguments passed to functions is suddenly conceived of as a space of elements which are functions whose operation is to induce another function to be evaluated at them.
You could think of a function like sin as being an infinite map from numbers to numbers, you give sin a number, sin gives you some associated number back, like sin(3) or something.
But then you could also think of the number 3 as an infinite map from functions to numbers, you give 3 a function f and 3 gives you some associated number, namely f(3).
I'm finding cases where I'd like some efficient syntax to suddenly view "arguments" or "elements" as "function-call-inducers" but most things, e.g. my lambda approach above, seem clunky.
Another thought I had was to write wrapper classes for the "elements" where this occurs. Something like:
from __future__ import print_function
class MyFloat(float):
def __call__(self, f):
return f(self)
m = MyFloat(3)
n = MyFloat(2)
MyFloat(m + n)(type)
MyFloat(m + n)(print)
which will print __main__.MyFloat and 5.0.
But this requires a lot of overhead to redefine data model operators and so on, and clearly it's not a good idea to push around your own version of very basic things like float which will be ubiquitous in most programs. It's also easy to get it wrong, like from my example above, doing this:
# Will result in a recursion error.
MyFloat(3)(MyFloat(4))
There is no built-in function for that. Simply because that's definitely not a commonly used concept. Plus Python is not designed to solve mathematical problems.
As for the implementation here's the shortest one you can get IMHO:
rev_map = lambda x, seq: [f(x) for f in seq]
Note that the list comprehension is so short and easy that wrapping it with a function seems to be unnecessary in the first place.

Getting an expression over a horizon for a given recursive equation in sympy/numpy

The following example is stated just for the purpose of precise definition of the query. Consider a recursive equation x[k+1] = a*x[k] where a is some constant. Now, is there an easier way or an existing method within sympy/numpy that does the following (i.e., gives an expression over a horizon for a given recursive equation):
def get_expr(init, num):
a = Symbol('a')
expr = init
for i in range(num):
expr = a*expr
return expr
x0 = Symbol('x0')
get_expr(x0,3)
Horizon above is 3.
I was going to suggest using SymPy's rsolve to try to find a closed form solution to your equation, but it seems that at least for this specific one, there is a bug that prevents it from working. See http://code.google.com/p/sympy/issues/detail?id=2943. Maybe if you really want to know for a more complicated expression you could try that. For this one, the closed form solution is just a**n*x0.
Aside from that, SymPy doesn't have any functions that would do this evaluation directly, but it does have some things that can help. There are some memoization decorators in sympy.utilities.memoization that are made for internal use, but should work just fine for external uses. They can help make your evaluation more efficient by caching the result of previous evaluations. You'll need to write the get_expr recursively for it to work effectively. Or you could just write your own cacher. It's not that complicated.

Categories

Resources