Search code examples
functionsubstitutionmaple

Define function with property f(a,b,c) = f(c,a,b) = f(b,c,a)


Is it possible in Maple to define a function (or operator) with property f(a,b,c) = f(c,a,b) = f(b,c,a), but not necessary other cases like f(a,b,c) = f(a,c,b). In Maple it should work like this:

[> f(a,b,c)-f(c,a,b), f(a,b,c)-f(b,c,a), f(a,b,c)-f(a,c,b);
                   0, 0, f(a,b,c)-f(a,c,b)

That is, function f could be non symmetric, but it shouldn't change under the substitution [a=b,b=c,c=a]:

[> f(a,b,c)-subs([a=b,b=c,c=a],f(a,b,c));
                   0

Just to make it clear: the question isn't about giving an example of such function, but about defining such property of function f in Maple, so that it would work as described (Maple would simplify the expression f(a,b,c)-f(c,a,b) to zero for any a,b,c).


Solution

  • I don't offhand see a way to accomplish this using just the define command. But there are alternative mechanisms.

    One of the tricky aspects involves getting Maple's - (minus) to discern the equivalence while still allowing all calls to f to return unevaluated with the original order of arguments.

    Relaxing that aspect for the time being, here's one easy idea. Devise f such that it rotates the arguments into a canonical order. The precise nature of the canonicalization may not matter -- here I happen to rotate according to the position of the entry with smallest memory address, but I could also have devised it with a lexicographic measurement.

    restart;
    
    f:=proc(x,y,z)
      local addr,i,m;
      addr:=map(:-addressof,[x,y,z]);
      m:=min[':-index'](addr);
      'procname'([x,y,z][[seq(`if`(m+i>3,(m+i) mod 3,
                                   m+i),i=0..2)]][]);
    end proc:
    
    f(a,b,c)-f(c,a,b), f(a,b,c)-f(b,c,a), f(a,b,c)-f(a,c,b);
    
                 0, 0, f(a, b, c) - f(a, c, b)
    

    That gets the results you described, as a consequence of the following behavior.

    f(a,b,c), f(b,c,a), f(c,a,b);
    
               f(a, b, c), f(a, b, c), f(a, b, c)
    
    f(a,c,b), f(b,a,c), f(c,b,a);
    
               f(a, c, b), f(a, c, b), f(a, c, b)
    

    You can see that the call f(c,b,a) actually returns the result f(a,c,b). Now, it's possible that you would also desire that,

    f(a,b,c) - f(c,b,a)
    

    returns as exactly that same expression. But the code above will return it as f(a,b,c) - f(a,c,b). If that is a problem for you then let me know. I can envision two other mechanisms, which involve changing how - works.

    The first is to rebind - to be procedure that can inspect the calls to f, while still returning them unevaluated (identical to the inputs) if they don't cancel each other arithmetically. This would just affect - when you call it from the top level. It wouldn't always affect how - works when called within other stock Library commands.

    Another way would be to construct the calls to f as objects which export their own static - method.