13Function Symbols

A function \(f(x,y)\) whose name is \(f\) and whose arguments are \(x,y\), but whose body is undefined, is often written on paper by abbreviating \(f\) and omitting the arguments. Function symbols (function symbol) are the feature for introducing this notation of abbreviating arguments of symbolic functions into programming. Although the motivation for function symbols is simple, since they are a language feature unique to Egison, we dedicate an entire chapter to introducing them, including their implementation.

13.1Basic Usage of Function Symbols

Function symbols are particularly powerful when dealing with computations involving differentiation. In the following, we define a function symbol f that takes x and y as arguments. Function symbols are treated as mathematical expressions of type MathValue.

declare symbol x, y, z

def f : MathValue := function (x, y)

When a function symbol is displayed with show, the argument values are always shown.

show f  -- "f x y"

As shown below, the function symbol f can be differentiated with respect to x or y. The resulting function from partial differentiation is displayed with the argument number appended using the | symbol. f|1 represents “the partial derivative of \(f\) with respect to the first argument,” and f|1|2 represents “the result of first differentiating with respect to the first argument and then with respect to the second argument.” “|” is a built-in symbol in Egison, similar to “_” and “~”. Below are display examples of differentiation of function symbols in both standard Egison output and LaTeX format output. “\(\partial\)/\(\partial\)” is a library function defined in Egison.

show (`$\partial$`/`$\partial$` f x)          -- "f|1 x y"
show (`$\partial$`/`$\partial$` (`$\partial$`/`$\partial$` f x) y) -- "f|1|2 x y"

Since f is a function of x and y, differentiating with respect to z returns 0 as follows.

show (`$\partial$`/`$\partial$` f z) -- "0"

In physics calculations, functions with four arguments \(t,x,y,z\) frequently appear. Without a mechanism like function symbols, expressions would become long and difficult to read, so the function symbol mechanism improves program readability and writability.

13.2Substituting Values into Arguments

Values can be substituted into function symbol arguments using the same syntax as ordinary function application. Writing f 0 1 yields the expression with 0 substituted for the first argument and 1 for the second argument of f. An error occurs if the number of arguments does not match.

show (f 0 1)   -- "f 0 1"
show (f x 0)   -- "f x 0"

The result of substituting arguments is also a mathematical expression of type MathValue, so it can be further differentiated. When a concrete numerical value is substituted for an argument, differentiation with respect to that argument yields 0.

`$\partial$`/`$\partial$` (f 0 1) x -- 0

The V.substitute function can also be used to replace arguments.

V.substitute [|x, y|] [|0, 0|] f
-- f 0 0

13.3Chain Rule for Composite Functions

An important feature of Egison's function symbols is their support for the chain rule of composite functions. The reason the function expression takes expressions rather than variable names as formal parameters is to support differentiation of composite functions. As before, let \(g\) be an abbreviation for \(g(x,y)\). Also assume the relations \(x=r \cos \theta, y= r \sin \theta\). Then, differentiating \(g\) with respect to \(r\) returns the result \(\frac{\partial g}{\partial x_1} \cos \theta + \frac{\partial g}{\partial x_2} \sin \theta\) by the chain rule.

declare symbol r, `$\theta$`

def x : MathValue := r * cos `$\theta$`
def y : MathValue := r * sin `$\theta$`
def g : MathValue := function (x, y)

show g
-- "g (('cos θ) * r) (('sin θ) * r)"

show (`$\partial$`/`$\partial$` g r)
-- "('sin θ) * (g|2 (('cos θ) * r) (('sin θ) * r))
--    + ('cos θ) * (g|1 (('cos θ) * r) (('sin θ) * r))"

The symbols g|1 and g|2 appearing in the result of partial differentiation represent \(\frac{\partial g}{\partial x_1}\) and \(\frac{\partial g}{\partial x_2}\) respectively (the argument number is appended using the | symbol). Since the argument values are always included in the display, it is clear at which point the partial derivative coefficients are evaluated.

13.4Tensors with Function Symbol Components

In mathematics and physics, functions sometimes appear as components of tensors. For example, this occurs when representing vector fields or tensor fields. Egison allows function symbols to be used as components of tensors. As shown in the following example, when a tensor's components are function symbols, function symbols are generated with names formed by appending the component position indices to the variable name to which the tensor is bound.

declare symbol x, y, z

def g_i_j : Tensor MathValue := generateTensor
      (\match as list integer with
         | [$n, #n] -> function (x, y, z)
         | _ -> 0)
      [3, 3]

show (withSymbols [i, j] g_i_j)
-- "[| [| g_1_1 x y z, 0, 0 |], [| 0, g_2_2 x y z, 0 |], [| 0, 0, g_3_3 x y z |] |]"

show (withSymbols [i, j] (`$\partial$`/`$\partial$` g_i_j x))
-- "[| [| g_1_1|1 x y z, 0, 0 |], [| 0, g_2_2|1 x y z, 0 |], [| 0, 0, g_3_3|1 x y z |] |]"

13.5Internal Representation and Pattern Matching of Function Symbols

Function symbols are internally represented in Egison as factors that have a name and a list of argument values (they are one kind of factor of the mathematical expression data introduced in Section 10.1).

The func pattern constructor can be used to pattern match on function symbols. The first argument of this pattern matches the function name, and the second argument matches the list of argument values.

declare symbol x, y
def f : MathValue := function (x, y)

match f as mathValue with
  | func $name $args -> (name, args)
-- (f, [x, y])

In the differentiation implementation of the library, the number of arguments is used to extract the partial derivative coefficient for each argument using integer indices. The following is an excerpt of the part of the library (lib/math/analysis/derivative.egi) that differentiates function symbols.

def chainPartialDiffBuiltin (v : MathValue) (dx : MathValue)
  : MathValue :=
  match v as mathValue with
    | func _ $args ->
       sum (map2 (\s r -> (userRefs v [s]) * partialDiff r dx)
                 (between 1 (length args))
                 args)
    ...

Here, between 1 (length args) generates the list of integers [1, 2, ..., n]. userRefs f [1] returns the expression f|1 x y, which applies the name symbol of f with the integer index 1 appended.

13.6Implementation of Function Symbols

An important aspect of the function symbol implementation is that function symbols retain their own names. For this purpose, the Egison interpreter keeps track of the name of the variable currently being defined. Additionally, to support function symbols appearing as tensor components as described in Section 13.4, it is necessary to track the position of the tensor component currently being defined. For this purpose, the Egison interpreter also keeps track of the position of the tensor component being defined. In the Egison interpreter implementation, these are managed as additional components of the environment threaded through the evaluator.

This book in another language: English, 日本語