I have a variety of SymPy expressions involving UndefinedFunction instances:
f = Function('f')
g = Function('g')
e = f(x) / g(x)
How can I obtain a list of the function invocations appearing in such expressions? In this example, I'd like to get [f(x), g(x)].
I'm aware of free_symbols but it kicks back set([x]) (as it should).
You are right that you want to use atoms, but be aware that all functions in SymPy subclass from Function, not just undefined functions. So you'll also get
>>> (sin(x) + f(x)).atoms(Function)
set([f(x), sin(x)])
So you'll want to further reduce your list to only those functions that are UndefinedFunctions. Note that UndefinedFunction is the metaclass of f, so do to this, you need something like
>>> [i for i in expr.atoms(Function) if isinstance(i.__class__, UndefinedFunction)]
[f(x)]
It turns out that the atoms member method can accept a type on which to filter. So
e.atoms(Function)
returns
set([f(x), g(x)])
as I'd wanted. And that fancier things like
e.diff(x).atoms(Derivative)
are possible.
Related
I am trying to understand about sympy's symbolic functions:
import sympy
from sympy.abc import x,y,z
with sympy.evaluate(False):
print(sympy.sympify("diff(x,x)").func)
print(sympy.parse_expr("diff(x, x)", local_dict={'diff':sympy.Derivative}).func)
print(sympy.sympify("Derivative(x,x)").func)
pass
This puts out:
Piecewise
<class 'sympy.core.function.Derivative'>
<class 'sympy.core.function.Derivative'>
This example should illustrate that diff is not a symbolic function yet Derivative is.
sympy.sympify("diff(x,x)").func results in Piecewise.
What exactly makes a function in sympy 'symbolic'?
Why don't both of the functions belong to <class 'sympy.core.function.Derivative'>?
I tried to test on a few examples if a function is symbolic using:
list_of_funcs = [sin, cos, tan, sec, csc, cot, sinh, cosh, tanh, sech, csch, coth, asin, acos, atan, asec, acsc, acot, asinh, acosh, atanh, asech, acsch, acoth, log, log, log, exp, <class 'sympy.concrete.summations.Sum'>, <class 'sympy.concrete.products.Product'>, Piecewise, jacobi, Piecewise]
with sympy.evaluate(False):
for f in list_of_funcs:
if issubclass(f, sympy.Basic):
print(f'{f}: True')
It returned True for all yet as far as I understood Piecewise is not symbolic.
Could you help me finding a way to test if a function is symbolic?
Answering this question without going too deep into coding concepts is not easy, but I can give it a try.
SymPy exposes many functions:
cos, sin, exp, Derivative, Integral... we can think of them as symbolic functions. Let's say you provide one or more arguments, then:
the function might evaluate to some symbolic numerical value. For example, cos(0) will return the symbolic number 1.
the function might return an "unevaluated" object. For example, cos(x) returns cos(x): this is a symbolic expression of type cos (as you have seen by running the func attribute). Similarly, you can create a derivative object Derivative(expr, x): this is a symbolic expression that represents a derivative, it doesn't actually compute the derivative!
Unevaluate functions, for example Function("f")(x), which will render as f(x): this is a symbolic expression of type f.
diff, integrate, series, limit, ... : those are ordinary python functions (for example, created with def diff(...)) that are going to apply some operation to a symbolic expression. When you call diff(expr, x) you are asking SymPy to compute the derivative of expr with respect to x. What if you wanted to represent the derivative without actually computing it? You write Derivative(expr, x).
So, going back to your example:
sympy.parse_expr("diff(x, x)", local_dict={'diff':sympy.Derivative})
this can be easily simplified to:
sympy.parse_expr("Derivative(x, x)")
A few more "relationships":
diff and Derivative
integrate and Integral
limit and Limit
Think of "symbolic" functions as nouns and "non symbolic" as verbs.
noun-like verb-like
---------- ---------
Integral integrate
Derivative diff
Sum summation
Product product
Those that are Python functions (I think what you mean by non-symbolic) emit some evaluated form of something that could also exist in an unevaluated form, e.g. prod(x, (x, 1, 5)) -> 120; Product(x, (x, 1, 5)) -> no change.
It would be better to refer to them in some other way. What I think you mean is "evaluated" vs "non-evaluated" (since almost all of SymPy's functions will return SymPy objects with "symbols", even if numeric).
If the type(thing) -> function it is not a class itself, it is a Python function. If you check the type of cos or Sum you will not get function as the result.
Whereas some of the evaluates and unevaluated forms may have different names (Sum vs summation) others, like Add are evaluative by default but you can use the evaluate=False arg to stop that: Add(x, x) = x + x != Add(x,x,evaluate=False). Those which are evaluative can be made non-evaluative by passing evaluate=True, e.g. Derivative(x, x, evaluate=True) -> 1.
I have the following 'issue' with sympy at the moment:
I have a symbolic expression like M = matrix([pi*a, sin(1)*b]) which I want to lambdify and pass to a numerical optimizer. The issue is that the optimizer needs the function to input/output numpy arrays of shape (n,) and specifically NOT (n,1).
Now I have been able to achieve this with the following code (MWE):
import numpy as np
import sympy as sp
a, b = sp.symbols('a, b')
M = sp.Matrix([2*a, b])
f_tmp = sp.lambdify([[a,b]], M, 'numpy')
fun = lambda x: np.reshape( f_tmp(x), (2,))
Now, this is of course extremely ugly, since the reshape needs to be applied every time fun is evaluated (which might be LOTS of times). Is there a way to avoid this problem? The Matrix class is by definition always 2 dimensional. I tried using sympy's MutableDenseNDimArray-class, but they don't work in conjunction with lambdify. (symbolic variables don't get recognized)
One way is to convert a matrix to a nested list and take the first row:
fun = sp.lambdify([[a, b]], M.T.tolist()[0], 'numpy')
Now fun([2, 3]) is [4, 3]. This is a Python list, not a NumPy array, but optimizers (at least those in SciPy) should be okay with that.
One can also do
fun = sp.lambdify([[a, b]], np.squeeze(M), 'numpy')
which also returns a list.
In my test the above were equally fast, and faster than the version with a wrapping function (be it np.squeeze or np.reshape): about 6 µs vs 9 µs. It seems the gain is in eliminating one function call.
In a dynamic system my base values are all functions of time, d(t). I create the variable d using d = Function('d')(t) where t = S('t')
Obviously it's very common to have derivatives of d (rates of change like velocity etc.). However the default printing of diff(d(t)) gives:-
Derivative(d(t), t)
and using pretty printing in ipython (for e.g.) gives a better looking version of:-
d/dt (d(t))
The functions which include the derivatives of d(t) are fairly long in my problems however, and I'd like the printed representation to be something like d'(t) or \dot(d)(t) (Latex).
Is this possible in sympy? I can probably workaround this using subs but would prefer a generic sympy_print function or something I could tweak.
I do this by substitution. It is horribly stupid, but it works like a charm:
q = Function('q')(t)
q_d = Function('\\dot{q}')(t)
and then substitute with
alias = {q.diff(t):q_d, } # and higher derivatives etc..
hd = q.diff(t).subs(alias)
And the output hd has a pretty dot over it's head!
As I said: this is a work-around and works, but you have to be careful in order to substitute correctly (Also for q_d.diff(t), which must be q_d2 and so on! You can have one big list with all replacements for printing and just apply it after the relevant mathematical steps.)
The vector printing module that you already found is the only place where such printing is implemented in SymPy.
from sympy.physics.vector import dynamicsymbols
from sympy.physics.vector.printing import vpprint, vlatex
d = dynamicsymbols('d')
vpprint(d.diff()) # ḋ
vlatex(d.diff()) # '\\dot{d}'
The regular printers (pretty, LaTeX, etc) do not support either prime or dot notation for derivatives. Their _print_Derivative methods are written so that they also work for multivariable expressions, where one has to specify a variable by using some sort of d/dx notation.
It would be nice to have an option for shorter derivative notation in general.
I'm trying to figure out if there is a macro similar to delay in clojure to get a lazy expression/ variable that can be evaluated later.
The use case is a default value for Map.get/3, since the default value comes from a database call, I'd prefer it to be called only when it's needed.
Elixir's macro could be used for writing simple wrapper function for conditional evaluation. I've put one gist in the following, though it may be better/smarter way.
https://gist.github.com/parroty/98a68f2e8a735434bd60
"Generic" laziness is a bit of a tough nut to crack because it's a fairly broad question. Streams allow laziness for enumerables but I'm not sure what laziness for an expression would mean. For example what would a lazy form of x = 1 + 2 be? When would it be evaluated?
The thought that comes to mind for a lazy form of an expression is a procedure expression:
def x, do: 1 + 2
Because the value of x wouldn't be calculated until the expression is actually invoked (as far as I know). I'm sure others will correct me if I'm wrong on that point. But I don't think that's what you want.
Maybe you want to rephrase your question--leaving out streams and lazy evaluation of enumerated values.
One way to do this would be using processes. For example the map could be wrapped in a process like a GenServer or an Agent where the default value will be evaluated lazy.
The default value can be a function which makes the expensive call. If Map.get/3 isn't being used to return functions you can check if the value is a function and invoke it if it is returned. Like so:
def default_value()
expensive_db_call()
end
def get_something(dict, key) do
case Map.get(dict, key, default_value) do
value when is_fun(value) ->
value.() # invoke the default function and return the result of the call
value ->
value # key must have existed, return value
end
end
Of course if the map contains functions this type of solution probably won't work.
Also check Elixir's Stream module. While I don't know that it would help solve your particular problem it does allow for lazy evaluation. From the documentation:
Streams are composable, lazy enumerables. Any enumerable that generates items one by one during enumeration is called a stream. For example, Elixir’s Range is a stream:
More information is available in the Stream documentation.
Map.get_lazy and Keyword.get_lazy hold off on generating the default until needed, links the documentation below
https://hexdocs.pm/elixir/Map.html#get_lazy/3
https://hexdocs.pm/elixir/Keyword.html#get_lazy/3
You can wrap it in an anonymous function, then it will be evaluated when the function is called:
iex()> lazy = fn -> :os.list_env_vars() end
#Function<45.79398840/0 in :erl_eval.expr/5>
iex()> lazy.()
I am trying to test whether any sub-expression contains a sin function (or any trig function)
from sympy import sin, symbols, Wild
A, B, x, y = symbols('A, B, x, y')
W1=Wild('W1')
I can do this:
>> (A*sin(x)+B*sin(y)).has(sin(x))
out: True
But this does not work:
>>: (A*sin(x)+B*sin(y)).has(sin(W1))
out: False
How do I test for one or more sin functions regardless of argument?
If you want to use Wilds, use find:
In [11]: (A*sin(x)+B*sin(y)).find(sin(W1))
Out[11]: set([sin(x), sin(y)])
But if you are searching for a single function like sin, and not generic expressions, an easier and faster way is to use atoms:
In [12]: (A*sin(x)+B*sin(y)).atoms(sin)
Out[12]: set([sin(x), sin(y)])
If you want to check for multiple trig functions, atoms takes multiple arguments, which is more efficient than calling it multiple times
In [14]: (A*sin(x)+B*cos(y)).atoms(sin, cos)
Out[14]: set([sin(x), cos(y)])
In my first attempt, I tried to test for sin using a wild card for an argument
>>: (A*sin(x)+B*sin(y)).has(sin(W1))
out: False
After reading asmeuer's answer and experimenting a bit, I discovered that you can simply pass the class sin (no argument) and it works:
>>: (A*sin(x)+B*sin(y)).has(sin, cos)
out: True
Thus, use has if you want a logical test and use atoms if you want a set of the functions that appear in the expression.
Question: is there a general class I can use to test for the presence of any trig function (sin, cos, tan, atan, ...)?