# Revision history [back]

### Defining a symmetric function

I am new to Sage (about a week) and I would like to define a symbolic function called s that doesn't evaluate to anything, but it has to be symmetric.

So if I type s(3,2) the output must be s(2,3), or typing s(1,4,3,2) the output must be s(1,2,3,4) etc.

Is it possible to have such a definition? I am searching the documentation to try to implement this, but so far no luck.

I tried using the function sort_subscript() that I found in the tensor.pdf documentation, but the attempt below obviously fails in an infinite loop:

def s(*m): a=sort_subscript(m); return s(a);

How can I implement this? My motivation is that s(i,j) are the symmetric Mandelstam invariants in a scattering amplitude context.

### Defining a symmetric function

I am new to Sage (about a week) and I would like to define a symbolic function called s that doesn't evaluate to anything, but it has to be symmetric.

So if I type s(3,2) the output must be s(2,3), or typing s(1,4,3,2) the output must be s(1,2,3,4) etc.

Is it possible to have such a definition? I am searching the documentation to try to implement this, but so far no luck.

I tried using the function sort_subscript() * that I found in the tensor.pdf documentation, but the attempt below obviously fails in an infinite loop:

def s(*m):
a=sort_subscript(m);
return s(a);s(a);


How can I implement this? My motivation is that s(i,j) are the symmetric Mandelstam invariants in a scattering amplitude context.

### Defining a symmetric function

I am new to Sage (about a week) and I would like to define a symbolic function called s that doesn't evaluate to anything, but it has to be symmetric.

So if I type s(3,2) the output must be s(2,3), or typing s(1,4,3,2) the output must be s(1,2,3,4) etc.

Is it possible to have such a definition? I am searching the documentation to try to implement this, but so far no luck.

I tried using the function sort_subscript()* that I found in the tensor.pdf documentation, but the attempt below obviously fails in an infinite loop:

def s(*m):
a=sort_subscript(m);
return s(a);


How can I implement this? My motivation is that s(i,j) are the symmetric Mandelstam invariants in a scattering amplitude context.

Edit:

Today I tried this:

class s(BuiltinFunction):
def __init__(self, x1, x2):
if x2 >= x1:
self.x = x1
self.y = x2
BuiltinFunction.__init__(self,'s(%s,%s)' % (x1,x2))
else:
self.x = x2
self.y = x1
BuiltinFunction.__init__(self,'s(%s,%s)' % (x2,x1))


And it works in the sense that sage: s(4,2) s(2,4)

However, this is not complete since

sage: 2*s(4,2)
...
TypeError: unsupported operand parent(s) for '*': 'Integer Ring' and '<class '__main__.s'>'


where I would expect the answer 2*s(2,4). So it is not so simple and I couldn't get a working definition for the __mul__ method and it just looked like the wrong approach anyway.

So is it possible to define a symmetric function that behaves like this inside the user interface?

Alternatively, it would be nice if there was an argument to the built-in function() to specify the symmetry,

s = function('s', nargs=2, sym='symmetric')


### Defining a symmetric function

I am new to Sage (about a week) and I would like to define a symbolic function called s that doesn't evaluate to anything, but it has to be symmetric.

So if I type s(3,2) the output must be s(2,3), or typing s(1,4,3,2) the output must be s(1,2,3,4) etc.

Is it possible to have such a definition? I am searching the documentation to try to implement this, but so far no luck.

I tried using the function sort_subscript()* that I found in the tensor.pdf documentation, but the attempt below obviously fails in an infinite loop:

def s(*m):
a=sort_subscript(m);
return s(a);


How can I implement this? My motivation is that s(i,j) are the symmetric Mandelstam invariants in a scattering amplitude context.

Edit:

Today I tried this:

class s(BuiltinFunction):
def __init__(self, x1, x2):
if x2 >= x1:
self.x = x1
self.y = x2
BuiltinFunction.__init__(self,'s(%s,%s)' % (x1,x2))
else:
self.x = x2
self.y = x1
BuiltinFunction.__init__(self,'s(%s,%s)' % (x2,x1))


And it works in the sense that that

   sage: s(4,2)
s(2,4)s(2,4)


However, this is not complete since

sage: 2*s(4,2)
...
TypeError: unsupported operand parent(s) for '*': 'Integer Ring' and '<class '__main__.s'>'


where I would expect the answer 2*s(2,4). So it is not so simple and I couldn't get a working definition for the __mul__ method and it just looked like the wrong approach anyway.

So is it possible to define a symmetric function that behaves like this inside the user interface?

Alternatively, it would be nice if there was an argument to the built-in function() to specify the symmetry,

s = function('s', nargs=2, sym='symmetric')


### Defining a symmetric function

I am new to Sage (about a week) and Updated question:

I would like to define a generic symbolic function called s that doesn't evaluate to anything, but it has to be whose arguments are totally symmetric.

So if I type s(3,2) the output must be s(2,3), or typing s(1,4,3,2) the output must be s(1,2,3,4) etc.

   sage: s(3,2)
s(2,3)


and similarly

   sage: s(3,4,1,2)
s(1,2,3,4)


and in general some arbitrary product

   sage: s(3,2)*s(1,2)^2*s(5,4,1)
s(2,3)*s(1,2)^2*s(1,4,5)


Is it possible to have such a definition? I am searching the documentation to try to implement this, but so far no luck.

I tried using the function sort_subscript()* that I found in the tensor.pdf documentation, but the attempt below obviously fails in an infinite loop:

def s(*m):
a=sort_subscript(m);
return s(a);


How can I implement this? My motivation is that s(i,j) are the symmetric Mandelstam invariants in a scattering amplitude context.

Edit:

Today I tried this:

class s(BuiltinFunction):
def __init__(self, x1, x2):
if x2 >= x1:
self.x = x1
self.y = x2
BuiltinFunction.__init__(self,'s(%s,%s)' % (x1,x2))
else:
self.x = x2
self.y = x1
BuiltinFunction.__init__(self,'s(%s,%s)' % (x2,x1))


And it works in the sense that

   sage: s(4,2)
s(2,4)


However, this is not complete since

sage: 2*s(4,2)
...
TypeError: unsupported operand parent(s) for '*': 'Integer Ring' and '<class '__main__.s'>'


where I would expect the answer 2*s(2,4). So it is not so simple and I couldn't get a working definition for the __mul__ method and it just looked like the wrong approach anyway.

So is it possible to define a symmetric function that behaves like this inside the user interface?

Alternatively, it It would be nice if there was an argument to the built-in function() to specify the symmetry,symmetry of its arguments. In this case I would get what I want with something like

s = function('s', nargs=2, sym='symmetric')


Partial solution from Apr/2017:

Upon reading Sage's source code I noticed the 'eval_func' option when defining functions. So I get (almost) what I want if I define this function

def symmetric(self, x1,x2):
if x1 < x2:
pass
else:
return self(x2,x1)


and use it together with 'eval_func'

 s = function("s", eval_func=symmetric)


Doing this works in the special case when the function contains two arguments:

  sage: 2*s(2,1)*s(6,5)^2
2*s(5, 6)^2*s(1, 2)


So the question now becomes: how can I extend this definition to a function with an arbitrary number of arguments?

### Defining a symmetric function

Updated question:

I would like to define a generic symbolic function called s whose arguments are totally symmetric.

So if I type s(3,2) the output must be s(2,3),

   sage: s(3,2)
s(2,3)


and similarly

   sage: s(3,4,1,2)
s(1,2,3,4)


and in general some arbitrary product

   sage: s(3,2)*s(1,2)^2*s(5,4,1)
s(2,3)*s(1,2)^2*s(1,4,5)


Is it possible to have such a definition? It would be nice if there was an argument to the built-in function() to specify the symmetry of its arguments. In this case I would get what I want with something like

s = function('s', sym='symmetric')


Partial solution from Apr/2017:

Upon reading Sage's source code I noticed the 'eval_func' option when defining functions. So I get (almost) what I want if I define this function

def symmetric(self, x1,x2):
if x1 < x2:
pass
else:
return self(x2,x1)


and use it together with 'eval_func'

 s = function("s", eval_func=symmetric)


Doing this works in the special case when the function contains two arguments:

  sage: 2*s(2,1)*s(6,5)^2
2*s(5, 6)^2*s(1, 2)


So the question now becomes: how can I extend this definition to a function with an arbitrary number of arguments?

### Defining a generic symbolic function with symmetric functionarguments

Updated question:

I would like to define a generic symbolic function called s whose arguments are totally symmetric.

So if I type s(3,2) the output must be s(2,3),

   sage: s(3,2)
s(2,3)


and similarly

   sage: s(3,4,1,2)
s(1,2,3,4)


and in general some arbitrary product

   sage: s(3,2)*s(1,2)^2*s(5,4,1)
s(2,3)*s(1,2)^2*s(1,4,5)


Is it possible to have such a definition? It would be nice if there was an argument to the built-in function() to specify the symmetry of its arguments. In this case I would get what I want with something like

s = function('s', sym='symmetric')


Partial solution from Apr/2017:

Upon reading Sage's source code I noticed the 'eval_func' option when defining functions. So I get (almost) what I want if I define this function

def symmetric(self, x1,x2):
if x1 < x2:
pass
else:
return self(x2,x1)


and use it together with 'eval_func'

 s = function("s", eval_func=symmetric)


Doing this works in the special case when the function contains two arguments:

  sage: 2*s(2,1)*s(6,5)^2
2*s(5, 6)^2*s(1, 2)


So the question now becomes: how can I extend this definition to a function with an arbitrary number of arguments?

Update 2:

For the moment I am using a less generic version as follows:

def symmetric(self, *x):

L = [i for i in x]
L0 = copy(L)
L.sort()

# to avoid a recursion
if L0 <= L:
pass
else:
size = len(L)
if size == 2:
return self(L,L)
elif size == 3:
return self(L,L,L)
elif size == 4:
return self(L,L,L,L)
elif size == 5:
return self(L,L,L,L,L)
else:
# doesn't work
return self(x)


I tried to make it generic with

  if L0 <= L:
pass
else:
return self(tuple(L))


but this doesn't work because the argument to self should be e.g. 1,2,3 and not the tuple (1,2,3).

### Defining a generic symbolic function with symmetric arguments

Updated question:

I would like to define a generic symbolic function called s whose arguments are totally symmetric.

So if I type s(3,2) the output must be s(2,3),

   sage: s(3,2)
s(2,3)


and similarly

   sage: s(3,4,1,2)
s(1,2,3,4)


and in general some arbitrary product

   sage: s(3,2)*s(1,2)^2*s(5,4,1)
s(2,3)*s(1,2)^2*s(1,4,5)


Is it possible to have such a definition? It would be nice if there was an argument to the built-in function() to specify the symmetry of its arguments. In this case I would get what I want with something like

s = function('s', sym='symmetric')


Partial solution from Apr/2017:

Upon reading Sage's source code I noticed the 'eval_func' option when defining functions. So I get (almost) what I want if I define this function

def symmetric(self, x1,x2):
if x1 < x2:
pass
else:
return self(x2,x1)


and use it together with 'eval_func'

 s = function("s", eval_func=symmetric)


Doing this works in the special case when the function contains two arguments:

  sage: 2*s(2,1)*s(6,5)^2
2*s(5, 6)^2*s(1, 2)


So the question now becomes: how can I extend this definition to a function with an arbitrary number of arguments?

Update 2:

For the moment I am using a less generic version as follows:

def symmetric(self, *x):

L = [i for i in x]
L0 = copy(L)
L.sort()

# to avoid a recursion
if L0 <= L:
L or len(L0) == 6:
pass
else:
size = len(L)
if size == 2:
return self(L,L)
elif size == 3:
return self(L,L,L)
elif size == 4:
return self(L,L,L,L)
elif size == 5:
return self(L,L,L,L,L)
else:
# doesn't work
return self(x)


I tried to make it generic with

  if L0 <= L:
pass
else:
return self(tuple(L))


but this doesn't work because the argument to self should be e.g. 1,2,3 and not the tuple (1,2,3).

### Defining a generic symbolic function with symmetric arguments

Updated question:

I would like to define a generic symbolic function called s whose arguments are totally symmetric.

So if I type s(3,2) the output must be s(2,3),

   sage: s(3,2)
s(2,3)


and similarly

   sage: s(3,4,1,2)
s(1,2,3,4)


and in general some arbitrary product

   sage: s(3,2)*s(1,2)^2*s(5,4,1)
s(2,3)*s(1,2)^2*s(1,4,5)


Is it possible to have such a definition? It would be nice if there was an argument to the built-in function() to specify the symmetry of its arguments. In this case I would get what I want with something like

s = function('s', sym='symmetric')


Partial solution Solution from Apr/2017:

Upon reading Sage's source code I noticed the 'eval_func' option when defining functions. So I get (almost) what I want if I define this function(following a suggestion of mforets, thanks!):

def symmetric(self, x1,x2):
*x):

L = list(x)
L0 = copy(L)
L.sort()

if x1 < x2:
L0 <= L:
pass
else:
return self(x2,x1)
self(*L)


and use it together with 'eval_func'define the (Mandelstam invariant) s as follows

 s = function("s", eval_func=symmetric)


Doing this works in the special case when the function contains two arguments:everything works. For example

  sage: 2*s(2,1)*s(6,5)^2
2*s(5, 2*s(2,1)*s(6,5,4,3)^2
2*s(3, 4, 5, 6)^2*s(1, 2)


So the I consider this question now becomes: how can I extend this definition to a function with an arbitrary number of arguments?

Update 2:

For the moment I am using a less generic version as follows:

def symmetric(self, *x):

L = [i for i in x]
L0 = copy(L)
L.sort()

# to avoid a recursion
if L0 <= L or len(L0) == 6:
pass
else:
size = len(L)
if size == 2:
return self(L,L)
elif size == 3:
return self(L,L,L)
elif size == 4:
return self(L,L,L,L)
elif size == 5:
return self(L,L,L,L,L)


I tried to make it generic with

  if L0 <= L:
pass
else:
return self(tuple(L))


but this doesn't work because the argument to self should be e.g. 1,2,3 and not the tuple (1,2,3).closed!