Operations with Functions

by

Rolf Sulanke

Mathematica v. 9.0.0.0
Date: January 18, 2013
New  test: June 14, 2014, with Mathematica v. 10.4.1.0
under  Linux, openSUSE Leap 42.1

In Mathematics  one often needs operations with functions as objects, not only with their values. In this notebook we discuss some problems we met trying to implement such operations into Mathematica.  First we tried to find a general solution. To this aim we had to clear certain Attributes of some Mathematica objects. It resulted that doing this is not to recommend in general, because Mathematica, running the program some time, automatically restores the disturbing deleted Attributes.
(?) This seems not to happen in the new test!
The only way out is to program each needed mathematical function individually, or to create such wanted properties as, e.g., the traditional notation of tensor components.
I thank Hubert Gollek for discussing the problems and a useful hint to Section 5.

Attributes of some  Built-In Functions

1. Addition of Functions

In Mathematica the addition of functions is not defined, the cell

(f+g)[x]

is not evaluated.  For working with tensors we developed the Mathematica package  tensalg.m. There we added  a rule for the addition of  functions as a rule for Plus:

Unprotect[Plus];Plus/:Plus[f_,g_][i___] := f[i] + g[i]; Protect[Plus];

Now we obtain

Clear[f,g];(f+g)[x]

(f-g)[x]

To evaluate the second term of the result we introduced the following

Unprotect[Times];Times/:(-g_)[x___] := -g[x];Protect[Times];

Now we get the expected evaluation:

(f-g)[x]

Warnings

1. Warning. Addition of Functions.  It remains to the user to control that the addition of  f, g in the expression f+g   makes sense. Formally can come out nonsense  as

(3+f)[x]

Therefore we left Plus untouched and defined an operation plus in tensalgv2.m

2. Warning. Addition of Functions.  In case g == -f the addition (f+g)[x] yields the expression 0[i] being undefined in Mathematica. The incorrect definition:
    Unprotect[Integer]; 0[i___] := 0; Protect[Integer]  
 leads to an unstable system (see below). Thus it remains only to set /.0[i] -> 0 after those expressions.

(f-f)[x]

(f-f)[x]/. 0[j_]-> 0

A direct definition fails

0[i___] := 0

(f-f)== 0

Defining 0[]

The list of all in the notebook globally defined symbols is obtained by

?Global`*

We try  the following incorrect definition:

Unprotect[Integer]; 0[___] := 0; Protect[Integer];

Then f - f works as expected (f+(-f))[x] yields 0

(f + (-f))[x]

(f-f)[x]

0[]

0[][]

(Sin - Sin)[1.]

Head[f - f]

Now the above correctly evaluated command yields strange error messages only
(?) In the new test all remained normal.

?Global`*

Thus to avoid further unexpected failures return to the normal state of Mathematica quitting the kernel and restarting the notebook.

2.  Multiplication of Functions

In Mathematica the expression

(f*g)[x]

is formally correct, but remains unevaluated.
Attempts to define argument wise multiplication of functions led to contradictions, e.g.

Clear[f,a,h,x]; Unprotect[Times]; 
Times/:Times[h_,f_][x___]  := h[x]*f[x];Protect[Times];

3*f[x]

(3*f)[x]

To delete this definition Quit the kernel and restart Mathematica.

We tried to define the product of general functions with an element only, introducing

Clear[f,a,h,x]; Unprotect[Times]; 
Times/:Times[h_,f_][x___]  := h*(f[x]);Protect[Times];

Also this leads to errors :

a*f[x]

(a*f)[x]

(3 *f)[x] == 3*(f[x])

The reason is that Times has the Attribute Orderless:

Attributes[Times]

yielding the product in a standard order of its factors :

Times [a,x,y,3,b,g,h]

Deleting this Attribute of Times

Unprotect[Times];Attributes[Times]= {Flat,Listable,NumericFunction,OneIdentity} ;
Times/: Times[a_,f_][x___] := a*(f[x]);
Protect[Times];

we obtain

Times [a,x,y,3,b,g,h]

Times [a,x,y,3.,b,g,h]

Times [a,x,y,Pi,b,2,g,h]

The  factors being numbers only are put at the first place, what is quite reasonable. Unfortunately, in Mathematica Pi is not a number:

NumberQ[Pi]

but it is Numeric

NumericQ[Pi]

Times[Pi,f]

(Pi*f)[x] == Pi*f[x]

(3. *f)[x] == 3.*f[x]

(a*f)[x]== a*f[x]

(y*f)[x]== y*f[x]

Unfortunately, running the program some time, the system restores the built-in Attributes of  Times. Thus a consistent definition of h*f, f a function, on this way is impossible.
Evaluate the next cell after some time.

(?)In the new test Mathematica didn’t restore the Attribute Orderless of Times:

Attributes[Times]

In spite of the fact that now this Attribute isn’t present, the commutative rule is applied by Simplify:

b*a == a*b

Simplify[%]

3. The Only Way Out

The only way out to avoid errors operating with functions seems to be to program every operation individually.
Example.

f[x_] := x^2; g[x_] :=Sin[x]

F[x_] := f[x] + a*g[x]

Now the definition of F is associated with this symbol

?F

F

%[x]

%%[Pi]

4. Introducing Null[ ]

?Null

Null

%[]

Null[]

Applying  function operations there  may appear  an undefined expressions Null[ ]. Thus we entered the following enhancement of Null:

Unprotect[Null]; Null[___] := Null;  Protect[Null];

Null[1,2][3]

%== Null

%% == Null[]

Null == Null[]

As far this enhancement doesn't lead to errors.

5. Traditional Notation in Tensor Calculus

In tensor algebra a very simple, but effective notation for the coordinate transformation is used: covariant indices are written below as Subscripts, and contravariant indices as Superscripts.

One may enter expressions as  ((Subscript[a, i2 j3])^(j1 j2 j3)) using the method found under

?Subsuperscript

click on >> and see the Details.

The following direct setting leads to errors:

a[{i_,j_},{k_}]:= ((Subscript[a, i j])^k)

The lower indices 1, 2  are multiplied, and the upper index is interpreted as  a power:

a[{1,2},{2}]

%== (Subscript[a, 2]) * (Subscript[a, 2])

Unfortunately,  the ambiguity in the mathematical use of superscript as indices, and, at the same time, as powers, doesn’t admit the use  of superscript indices for symbolic calculations.   Already  other authors  encountered this problem, see the following quotation from the notebook cartan.nb from “Tensors in Physics” of Harald H. Soleng, in which many special applications of tensors in physics may be found. 
Quotation:

Also in this program the Subsuperscript form of the tensor components may not be applied for symbolic calculations:

SWeylInvariant

Sum[(Superscript["C", "ijkl"])(Subscript["C", "ijkl"])" ", {i,4}]

End of the quotation.

Let us test the following definition, in which we denote the indices as super- and subscript lists :

Clear[tscript,ta,a,tb];
tscript[a_[{},{}]] := a;
tscript[a_[i_,{}] ]:= Subscript[a,i];
tscript[a_[{},j_] ]:= Superscript[a,j];tscript[a_[i_,j_] ]:= Superscript[Subscript[a,i],j];

tscript[a[{i2 ,i3},{j1, j2  ,j3}]]

tscript[b[{3},{1, 2 }]]

Sum[tscript[b[{i},{i,k}]] ,{i,3}]

Empty argument lists don’t appear:

tscript[a[{i2 ,i3},{}]]

tscript[a[{},{i2 ,i3}]]

tscript[a[{},{}]]

At first glance, this translation seems to work well.  But we get

(b^({i, k}))

(b^({2})) == {b*b}

Since Power  has  the Attribute Listable:

Attributes[Power]

{1,2,3}^2

Unfortunately, Power is mapped over Lists of exponents  too:

2^{1,2,3}

These rule is seldom used in mathematics, and therefore  it should not be implemented into Mathematica. Being preserved, a superscript list can not be interpreted as a tensor component:

(b^({i,j,k}))

The command

Unprotect[Power]; ClearAttributes[Power,Listable]; Protect[Power];

Attributes[Power]

seems to clear the situation :

(b^({i,j,k}))

(3^({i,j,k}))

After clearing the Attribute Listable of Power the Listable effect may be obtained using Map:

p[x_] := 3^x

Map[p,Range[5]]

q[x_] := x^2

Map[q,Range[5]]

Now the tensor component with a superscript index list appeared, but, unfortunately, Power gets the Attribute Listable back automatically, see below. 
Let us test the following translation of the tensor components in traditional form into the Mathematica format corresponding to the Definition:

Clear[a,i,j];stform[ ((Subscript[a_, j___])^(i___))]:= a[{j},{i}];
stform[ (Subscript[a_, j___])] :=a[{j},{}];
stform[ ((a_)^(i___))] := a[{},{i}];

Clear[b,tb,a];

stform[((Subscript[b, j,k])^i)]

stform[(Subscript[b, j,k])]

stform[(b^i)]

Unfortunately, the clearing of the attribute Listable will be reset automatically by Mathematica; evaluate the next two cells after some time:

(Subscript[b, {j,k}]^({i,j}))

3^{i,2}

Attributes[Power]

Thus, the superscript indices as lists would lead to errors, too.
(?) In the new test Mathematica preserved the changed Attributes!

In the following we use the subsuperscript notation for a simple conceptual description of tensor operations, and for the adaption to the traditional notation in differential geometry and relativity theory.  To obtain expressions  calculable in Mathematica one has to use the input form a[iList,jList], iList the  covariant, jList the contravariant indices. 
To get the  transition from the input form to the traditional form of the tensor components and vice versa  two simple functions may be useful:

tradf[a_[i_,j_]]:=Module[{ii = ToString[i],jj = ToString[j]},(Subscript[a, ii]^jj)]

bij =tradf[a[{i,j},{3,4}]]

FullForm[%]

Off[ToExpression::notstr]

Clear[a,i,j];mathf[(Subscript[a_, i_]^(j_))] :=a[ToExpression[i,InputForm],ToExpression[j,InputForm]]

mathf[bij]

FullForm[%]

bij/. (Subscript[a_, i_]^(j_))->mathf[(Subscript[a, i]^j)]

FullForm[%]

c[{2,i,k},{10}]/.a_[i_,j_]->tradf[a[i,j]]

tradf[c[{2,i,k},{10}]]

mathf[%]

FullForm[%]

Homepage

http://www2.mathematik.hu-berlin.de/~sulanke/