2
$\begingroup$

Here's my basic setup:

Say I have a list of specific symbols and a function noSymbol, which accepts a mathematica expression and checks whether any symbol from my list is contained in it, for example:

symbols = {basisElement};
noSymbol[x_] := And @@ ( Length[Position[x, #]] === 0 & /@ symbols );

An examle use-case could be that basisElement is a function enumerating basis vectors of some n-dimensional algebra, so that I could define the multiplication of the algebra as

mult[basisElement[i_], basisElement[j_]] := Sum[strucConst[i, j, k] * basisElement[k], {k, 1, n}];

with structConst the structure constants of the algebra.

Of course in this situation it is natural to define linear functions, and what I would often find myself doing is

Clear[f];
f[0] := 0;
f[v_ + w_] := f[v] + f[w];
f[a_ * v_] := a * f[v] /; noSymbol[a];
f[v_ * a_] := a * f[v] /; noSymbol[a];
(* actual function definition *)

at the beginning of every definition of a linear function.

This adds a lot of repetition to my code, so I wanted to ask if using a "linearizing function" like

linearize[f_] := (
    f[0] := 0;
    f[v_ + w_] := f[v] + f[w];
    f[a_ * v_] := a * f[v] /; noSymbol[a];
    f[v_ * a_] := a * f[v] /; noSymbol[a];
);

Clear[f];
linearize[f];
(* actual function definition *)

is considered good practices and makes sense, or if it could lead to any serious issues.

EDIT: Additionally, if this is good practice, how can I extend my linearize function so that it can "multilinearize"? For example, my multiplication from above would have to be linear in each argument.

$\endgroup$

1 Answer 1

1
$\begingroup$

First, a note regarding noSymbol: You can more easily implement it using FreeQ:

symbols = Alternatives[basisElement];
noSymbol := FreeQ[symbols]

Also, you don't need to define both f[a_ * v_] and f[v_ * a_], since Times is Orderless.

As for the actual question: I don't see any reason why this shouldn't be done, in fact, I've used very similar functions in the past.

Finally, for multi-linearization: You can do something like the following:

linearize[f_] := (
   f[___, 0, ___] := 0;
   f[pre___, v_ + w_, post___] := f[pre, v, post] + f[pre, w, post];
   f[pre___, a_ * v_, post___] := a*f[pre, v, post] /; noSymbol[a];
   );

Clear[f];
linearize[f];

f[a basisElement, c + d]
(* a f[basisElement, c] + a f[basisElement, d] *)

The rules simply apply the linearity properties to any argument, while keeping all the others (if any exist) unmodified

$\endgroup$
2
  • $\begingroup$ Thanks, I have never heard of FreeQ. Also, d'oh... the solution for multilinearization is so simple haha $\endgroup$
    – Jo Mo
    Jun 23, 2021 at 16:15
  • $\begingroup$ @JoMo FreeQ[symbols] is equivalent to FreeQ[#, symbols]& (note the order of the arguments) - this is also mentioned in the third usage form in the documentation of FreeQ (and in case you were not aware: similar so called "operator forms" exist for many functions, e.g. Map, Position, ...) $\endgroup$
    – Lukas Lang
    Jun 23, 2021 at 16:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.