I am wondering if there is an easy way to implement abstract mathematical Operators in Sympy. With operators I simply mean some objects that have 3 values as an input or 3 indices, something like "Operator(a,b,c)". Please note that I am refering to a mathematical operator (over a hilbert space) and not an operator in the context of programming. Depending on these values I want to teach Sympy how to multiply two Operators of this kind and how to multiply it with a float and so on. At some point of the calculation I want to replace these Operators with some others...
So far I couldn't figure out if sympy provides such an abstract calculation. Therefore I started to write a new Python-class for these objects, but this went beyond the scope of my limited knowledge in Python very fast... Is there a more easy way to implement that then creating a new class?
You may also want to look at SageMath, in addition to SymPy, since Sage goes to great lengths to come with prebuilt mathematical structures. However, it's been development more with eyes towards algebraic geometry, various areas of algebra, and combinatorics. I'm not sure to what extent it implements any operator algebra.
Yes, you can do this. Just create a subclass of sympy.Function. You can specify the number of arguments with nargs
class Operator(Function):
nargs = 3
If you want the function to evaluate for certain arguments, define the class function eval. It should return None for when it should remain unevaluated. For instance, to evaluate to 0 when all three arguments are 0, you might use
class Operator(Function):
#classmethod
def eval(cls, a, b, c):
if a == b == c == 0:
return Integer(0)
(note that nargs is not required if you define eval).
Related
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 was recently working with Python and wanted to use another way of finding square roots. For example I wanted to find square root of n with Newton-Raphson approximation. I need to overload the overload the ** (only when you raise a number to 0.5),o perator as well as math.sqrt(), because I have several older projects that could be sped up by doing so and replacing all math.sqrt() and **(0.5) with another function isn't ideal.
Could this be done in Python?
Is it possible to overload either ** or math.sqrt?
Any helpful links are also much appreciated.
def Square_root(n):
r = n/2
while(abs(r-(n/r)) > t):
r = 0.5 * (r + (n/r))
return r
print(2**(0.5)) ## changes to print(Square_root(2))
print(math.sqrt(2)) ## that also becomes print(Square_root(2))
In short: you can't change the behavior of __pow__ for built-in types.
Long answer: you can subclass the float, but it will require additional coding and refactoring of the input values of the program, to the new float class with overwritten operators and functions.
And you can overwrite the math.sqrt, but this is not recommended:
import math
math.sqrt = lambda x, y: print(x, y)
math.sqrt(3, 2)
# 3 2
This will require the custom function to have the same signature.
If you really want to overload languages int and float objects - you can use variants of magic functions. In order to be consistent, you'll have to write a lot of code.
A lot of work. Python is for lazy people - if you like to write a lot, stick to Java or C++ :)
Firstly, Sry fo the bad title of this question I simply don't know a better one.
If you have a better one => Tell me!
So my problem is that I would like to write a simplex solver in Python by myself to deeply understand how they work.
Therefore, I would like to have something like this in my program:
m.addConstr(x[0] <= 7)
Which basically should add a constraint to my model m.
This works in Gurobi which is just wonderful cause it's so easy to read.
The problem is that x[0] has to be an object where I itself can define what should happen when there is an inequality or equality or whatever, right?
I am happy to figure out most of the stuff by myself would just like to get an idea how this works.
It looks like you want to overload the comparison operators of whatever objects you're working with. So if Foo is the class of x[0] in your example, then you could write it like this:
class Foo:
def __gt__(self, other):
# construct and return some kind of constraint object
def __lt__(self, other):
# likewise
These special methods (__gt__, __ge__, __lt__, __le__, __ne__ and __eq__) are called for the left-hand object in a comparison relation. So if you have x > y, then the __gt__ method on x is called with y as an argument.
I don't think it should be your first concern to come up with an elegant input syntax. You should rather implement the simplex algorithm first.
I suggest, you handle the input by writing a parser for the two standard formats for linear programming problems: .lp and .mps
If you still want to know how to implement proper expression handling in Python I recommend you have a look at PySCIPOpt since this is exactly doing what you want and you can inspect the entire source code.
I would like to define my own operator. Does python support such a thing?
While technically you cannot define new operators in Python, this clever hack works around this limitation. It allows you to define infix operators like this:
# simple multiplication
x=Infix(lambda x,y: x*y)
print 2 |x| 4
# => 8
# class checking
isa=Infix(lambda x,y: x.__class__==y.__class__)
print [1,2,3] |isa| []
print [1,2,3] <<isa>> []
# => True
No, Python comes with a predefined, yet overridable, set of operators.
No, you can't create new operators. However, if you are just evaluating expressions, you could process the string yourself and calculate the results of the new operators.
Sage provides this functionality, essentially using the "clever hack" described by #Ayman Hourieh, but incorporated into a module as a decorator to give a cleaner appearance and additional functionality – you can choose the operator to overload and therefore the order of evaluation.
from sage.misc.decorators import infix_operator
#infix_operator('multiply')
def dot(a,b):
return a.dot_product(b)
u=vector([1,2,3])
v=vector([5,4,3])
print(u *dot* v)
# => 22
#infix_operator('or')
def plus(x,y):
return x*y
print(2 |plus| 4)
# => 6
See the Sage documentation and this enhancement tracking ticket for more information.
Python 3.5 introduces the symbol # for an extra operator.
PEP465 introduced this new operator for matrix multiplication, to simplify the notation of many numerical code. The operator will not be implemented for all types, but just for arrays-like-objects.
You can support the operator for your classes/objects by implementing __matmul__().
The PEP leaves space for a different usage of the operator for non-arrays-like objects.
Of course you can implement with # any sort of operation different from matrix multiplication also for arrays-like objects, but the user experience will be affected, because everybody will expect your data type to behave in a different way.
If you intend to apply the operation on a particular class of objects, you could just override the operator that matches your function the closest... for instance, overriding __eq__() will override the == operator to return whatever you want. This works for almost all the operators.
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.