How to alias a function to a symbol in SymPy - python

It's not clear from the documentation how one might easily define a function, based on existing SymPy functions, and alias it to a particular symbol for printing.
For example, I have defined the rectangular function as follows.
import sympy as sp
def rect(t):
return (sp.Heaviside(t + 1/2) - sp.Heaviside(t - 1/2))
While this is useful for the algebra side of things, preventing me from having to define a new Function subclass with derivatives and so forth, it would be nice if I could associate it with uppercase Pi (Π) so that expressions using it would print that instead of a series of Heaviside symbols.

Your rect would have to be a class rect(Function) instead of a function and it would need a custom printer. Note, too, that if you define the eval method as above (in terms of Heaviside) then your expression will no longer be the rect class...it will be an Add.
Another way to handle this would be to just use Function('\Pi')(t) in your expressions and when you are ready to do something with them, replace those instances with your definition. But what sorts of things do you want to do with the rect? Could you use a Piecewise instead?

Related

What's the name of this in python? [duplicate]

I'm beginning to appreciate the value of lambda expressions in python, particularly when it comes to functional programming, map, functions returning functions, etc. However, I've also been naming lambdas within functions because:
I need the same functionality several times and don't want to repeat code.
The functionality is specific to the function in which it appears; its not needed elsewhere.
When I encounter a situation that meets the above criteria, I've been writing a named lambda expression in order to DRY and narrowly scope functionality. For example, I am writing a function that operates on some numpy arrays, and I need to do some moderately tedious indexing of all the arrays passed to the function (which can easily fit on a single line). I've written a named lambda expression to do the indexing instead of writing a whole other function or copy/pasting the indexing several times throughout the function definition.
def fcn_operating_on_arrays(array0, array1):
indexer = lambda a0, a1, idx: a0[idx] + a1[idx]
# codecodecode
indexed = indexer(array0, array1, indices)
# codecodecode in which other arrays are created and require `indexer`
return the_answer
Is this an abuse of python's lambdas? Should I just suck it up and define a separate function?
Edits
Probably worth linking function inside function.
This is not Pythonic and PEP8 discourages it:
Always use a def statement instead of an assignment statement that
binds a lambda expression directly to an identifier.
Yes:
def f(x): return 2*x
No:
f = lambda x: 2*x
The first form means that the name of the resulting function object is
specifically 'f' instead of the generic '<lambda>'. This is more
useful for tracebacks and string representations in general. The use
of the assignment statement eliminates the sole benefit a lambda
expression can offer over an explicit def statement (i.e. that it can
be embedded inside a larger expression)
A rule of thumb for this is to think on its definition: lambdas expressions are anonymous functions. If you name it, it isn't anonymous anymore. :)
I've written a named lambda expression to do the indexing instead of writing a whole other function
Well, you are writing a whole other function. You're just writing it with a lambda expression.
Why not use def? You get nicer stack traces and more syntactical flexibility, and you don't lose anything. It's not like def can't occur inside another function:
def fcn_operating_on_arrays(array0, array1):
def indexer(a0, a1, idx):
return a0[idx] + a1[idx]
...

Where to put a function that acts on two instances of a specific class

This is really a design question and I would like to know a bit of what design patterns to use.
I have a module, let's say curves.py that defines a Bezier class. Then I want to write a function intersection which uses a recursive algorithm to find the intersections between two instances of Bezier.
What options do I have for where to put this functions? What are some best practices in this case? Currently I have written the function in the module itself (and not as a method to the class).
So currently I have something like:
def intersections(inst1, inst2): ...
def Bezier(): ...
and I can call the function by passing two instances:
from curves import Bezier, intersections
a = Bezier()
b = Bezier()
result = intersections(a, b)
However, another option (that I can think of) would be to make intersection a method of the class. In this case I would instead use
a.intersections(b)
For me the first choice makes a bit more sense since it feels more natural to call intersections(a, b) than a.intersections(b). However, the other option feels more natural in the sense that the function intersection really only acts on Bezier instances and this feels more encapsulated.
Do you think one of these is better than the other, and in that case, for what reasons? Are there any other design options to use here? Are there any best practices?
As an example, you can compare how the builtin set class does this:
intersection(*others)
set & other & ...
Return a new set with elements common to the set and all others.
So intersection is defined as a regular instance method on the class that takes another (or multiple) sets and returns the intersection, and it can be called as a.intersection(b).
However, due to the standard mechanics of how instance methods work, you can also spell it set.intersection(a, b) and in practice you'll see this quite often since like you say it feels more natural.
You can also override the __and__ method so this becomes available as a & b.
In terms of ease of use, putting it on the class is also friendlier, because you can just import the Bezier class and have all associated features available automatically, and they're also discoverable via help(Bezier).

I **really** need a function defined by user input. What are my options?

I'm writing a Python script that parses a user-inputted string defining a differential equation, such as 'x\' = 2*x'. My main problem is that I don't want to implement numerical solution methods myself, and instead rely on SciPy's solve_ivp method, for which a function such as
def my_de(t, x):
return 2*x
is absolutely necessary, since solve_ivp's first argument must be a function. Currently, I'm working around this problem with the following piece of code (in a simplified version):
var = 'x'
de = '2*x'
def my_de(t, y):
exec(f'{var} = {y}')
return eval(de)
A quick explanation for this terribleness: I do not know what variable the user's going to use in the input. var may be theta, it may be sleepyjoe, it may be donalddump. The only thing guaranteed is that the only variable on de is var. You can forget about t for the purposes of this post.
My question is, how can I avoid using exec and eval in this context? I know using any of these is a terrible idea, and I don't want to do it. However, I'm not really seeing any other option.
I am already parsing the user input beforehand, so I can try to make this safe (prohibited variable names, etc.), but anyone who wants to abuse this will be able to anyway.
In addition to the previous comments, another possibility is to evaluate the function definition itself:
userInput="2*x + x**3" # the input you wish to implement
exec("""def test(x): return {}""".format(userInput))
print(test(1.))
This will avoid the overhead of evaluating the userInput at each call.

How to use expand_log on matrix elements?

I want to simplify a sympy expression where the arguments are matrix elements using the function expand_log.
As a simple example let's look at the expression log(exp(x)), which should be simplified to x.
As the tutorial explains, simplifications will only be applied if the required assumptions hold, i.e. in this case, x must be real.
If I have a scalar quantity, I can specify this assumption when creating the variable as shown here.
However, I use a matrix symbol which does not allow specifying assumptions at creation. I instead tried using the new assumptions module:
import sympy as sym
from sympy.assumptions import assuming, Q
x = sym.MatrixSymbol('x',1,2)
expr = sym.log(sym.exp(x[0,0]))
with assuming(Q.real(x[0,0])):
display(sym.expand_log(expr))
The output still is log(exp(x[0, 0])).
So it seems to me that the expand_log function is not aware of the assumption that I specify in the assuming context manager.
Setting force=True yields the desired result but I want to avoid not checking assumptions at all.
Does anyone have an idea how to circumvent this problem?

Should I pass sympy symbols to functions?

Is there any disadvantage of not passing sympy symbols to functions?
def compute(alpha,a): #or def compute(a)
return 3*alpha+a
alpha = sympy.symbols("alpha")
expr = compute(alpha,3)
I don't have to pass alpha to compute() (I assume because it's a global variable), and right now, I think it makes the code better readable when I leave it out.
Is this considered bad design? I suppose this is a general "what to do with global variables in python" question, as has been asked here, but the answers said it would depend on the specific usecase.
I still have to create the alpha symbol before I call that function, it's just not obvious if i do not include it.
In contrast to lists (which the other question is about), SymPy treats symbols (and expressions) as immutable. Moreover, they are uniquely identified by the string you pass to Symbol or symbols. For illustration consider the following:
from sympy import Symbol
print({Symbol("a"), Symbol("a")})
>>> {a}
Therefore declaring a SymPy symbol as a global variable does not pose such a big issue – it’s like globally defining some mathematical constant. For example it cannot happen that some reasonable code using this symbol changes it.¹
So, depending on the context, it can make sense to:
define alpha globally,
pass alpha as a parameter to the function,
define alpha within the function at each call (which is possible, since symbols only depend on the associated string).
Without further context, it’s impossible to say which applies to your situation.
¹ Note that unreasonable code can still do this, e.g.:
from sympy.abc import a
from sympy.abc import a as a_2
a.name = "b"
print(a_2)
>>> b
Defining commonly used Symbols at the top of the file (i.e., globally) is perfectly good practice. As others have pointed out, even if it gets defined again, it won't really matter because two symbols with the same name are considered equal. One important caveat here: if you use assumptions, like real=True, then that does matter. So you should avoid using two symbols with the same name but different assumptions.
In your example, if alpha is always supposed to be the symbol Symbol('alpha'), then it doesn't make sense to have an argument to a function that never changes.
Another way you can do things, by the way, is to not have the function at all, but just use the expression with symbolic variables
alpha, a = symbols('alpha a')
expr = 3*alpha + a
and then use subs when you want to substitute a value
expr.subs({a: 3}) # or expr.subs(a, 3)

Categories

Resources