Ticket #6245 (needs_review enhancement)

Opened 9 months ago

Last modified 4 weeks ago

[with patch, needs review] make a custom infix operator decorator

Reported by: jason Owned by: cwitty
Priority: major Milestone: sage-4.3.4
Component: misc Keywords:
Cc: cwitty, hivert, mhansen, kcrisman Author(s): Jason Grout, Carl Witty, Florent Hivert
Report Upstream: N/A Reviewer(s):
Merged in: Work issues:

Description

It would be nice to incorporate the code developed in  http://groups.google.com/group/sage-devel/browse_thread/thread/100de89e7d402134/fe89570b403344ae (and in the same spirit as the backslash operator). An example of the final developed code is at  http://sagenb.org/home/pub/565.

Attachments

trac-6245-infix-decorator.patch Download (7.3 KB) - added by jason 6 months ago.

Change History

  Changed 9 months ago by jason

  • cc cwitty, hivert added

For reference, the code is:

class infix_operator:
    def __init__(self, function, left=None, right=None):
        self.function = function
        self.left = left
        self.right = right

    def __rmul__(self, left):
        if self.right is None:
            if self.left is None:
                return infix_operator(self.function, left=left)
            else:
                raise SyntaxError, "Infix operator already has its left argument"
        else:
            return self.function(left, self.right)

    def __mul__(self, right):
        if self.left is None:
            if self.right is None:
                return infix_operator(self.function, right=right)
            else:
                raise SyntaxError, "Infix operator already has its right argument"
        else:
            return self.function(self.left, right) 
        	

And several examples (doctests?) are:

# This emul operator returns the element-wise product of two lists...
@infix_operator
def emul(a,b):
    return [i*j for i,j in zip(a,b)] 
        	
a=[1,2,3]
b=[3,4,5]

# Returns [3,8,15]
a *emul* b 
        	
@infix_operator
def hadamard_product(a, b):
   if a.nrows()!=b.nrows() or a.ncols()!=b.ncols():
       raise ValueError, "Matrices must have the same dimensions in a Hadamard product"
   return matrix(a.nrows(), a.ncols(), [x*y for x, y in zip(a.list(), b.list())]) 
        	
A=random_matrix(ZZ,3)
B=random_matrix(ZZ,3)
A *hadamard_product* B 

  Changed 6 months ago by jason

The patch is an initial go at this. The documentation for the function needs to change (it still is just the same docs as the code I followed in plot/misc.py).

Here are some examples:

sage: from sage.misc.misc import infix_operator
sage: # A post-fix operator
sage: @infix_operator('or')
sage: def pipe(a,b):
...       return b(a)
...
sage: print (x |pipe| cos)
sage: print pi |pipe| n
sage: print pi |pipe| n |pipe| cos
cos(x)
3.14159265358979
-1.00000000000000
sage: # an infix dot product
sage: @infix_operator('multiply')
sage: def dot(a,b):
...       return a.dot_product(b)
...       
...
sage: vector([1,2]) *dot* vector([2,4])
10
sage: # an infix sum
sage: @infix_operator('add')
sage: def esum(a,b):
...       return [i+j for i,j in zip(a,b)]
...
sage: [1,2,4] +esum+ [3,-1,2]
[4, 1, 6]

  Changed 6 months ago by jason

  • cc mhansen added
  • summary changed from make a custom infix operator decorator to [with patch, needs work] make a custom infix operator decorator

CCing mhansen, since he probably has very enlightening things to say about how I dealt with the decorators :).

  Changed 6 months ago by jason

  • author set to Jason Grout, Carl Witty, Florent Hivert

  Changed 6 months ago by jason

I cleaned up the code a bit and made much better documentation.

Changed 6 months ago by jason

  Changed 6 months ago by jason

  • cc kcrisman added
  • summary changed from [with patch, needs work] make a custom infix operator decorator to [with patch, needs review] make a custom infix operator decorator

follow-up: ↓ 8   Changed 6 months ago by kcrisman

I have no comment on the technical side, but wonder - are you limiting "object" to be or, add, or multiply? What if someone wanted to create an infix for, say, factorial - would they have to change this code?

in reply to: ↑ 7   Changed 6 months ago by jason

Replying to kcrisman:

I have no comment on the technical side, but wonder - are you limiting "object" to be or, add, or multiply? What if someone wanted to create an infix for, say, factorial - would they have to change this code?

I only chose a few precedence levels (that's really the issue here). There's no reason we couldn't put all of the special functions in (like subtract, for example).

  Changed 4 weeks ago by rossk

  • upstream set to N/A

Applied patch to 4.3.2

(Cool functionality - Can review quickly once this is addressed)

applying trac-6245-infix-decorator.patch
patching file sage/misc/misc.py
Hunk #1 FAILED at 2219
1 out of 1 hunks FAILED -- saving rejects to file sage/misc/misc.py.rej
patch failed, unable to continue (try -v)
patch failed, rejects left in working dir
errors during apply, please fix and refresh trac-6245-infix-decorator.patch
Note: See TracTickets for help on using tickets.