Skip to content

Functions

Operators are mappings of functions to functions. In the following, we will learn about functions, function spaces (or function sets), and how these concepts are implemented in continuiti.

Functions

A function is a mapping between a set \(X\) (domain) and a set \(Y\) (co-domain), denoted by

\[\begin{align*} f: X &\rightarrow Y, \\ x &\mapsto f(x). \end{align*}\]

For example, the function \(f(x)=x^2\) maps each element \(x\in X = [-1,1] \subset \mathbb{R}\) to an element of \(Y = [0,1] \subset \mathbb{R}\).

In continuiti, functions are handled by a Function object that takes a callable as input. As an example, we define two functions \(f\) and \(g\):

\[ f(x) = \sin(\pi x), \qquad g(x) = x^3, \qquad x\in \mathbb{R}. \]
from continuiti.data.function import Function

f = Function(lambda x: torch.sin(torch.pi * x))
g = Function(lambda x: x ** 3)

Functions are evaluated by calling them.

x = torch.linspace(-1, 1, 100)
y = f(x)
z = g(x)
No description has been provided for this image

Functions can be added to other function instances and multiplied by scalars. For instance:

h_1 = f + g
h_2 = (-1) * (f + g)
No description has been provided for this image

Function Sets

Let \(X\) be a domain supported on a field \(K_1\), and let \(Y\) be the codomain supported on a field \(K_2\). A function space is the set of functions \(F(X, Y)\) that map from \(X\) to \(Y\) and are closed with respect to addition $$ (f+g)(x):X \rightarrow Y, x\mapsto f(x)+g(x), $$ and scalar multiplication $$ (c\cdot f)(x) \rightarrow Y, x\mapsto c\cdot f(x). $$

In practice, we consider subsets of function spaces (where in general, these properties are not respected) and, therefore, this class implements a (parametrized) function set. Here, we define the following set of sine waves $$ y = \beta \sin(k\pi x),\quad A=[\beta, k]^\top\in\mathbb{R}^2,\quad x, y\in\mathbb{R}. $$ In continuiti, function sets are handled by a FunctionSet that takes a nested callable as input. When FunctionSet is called with a set of parameters it returns a list of Function instances.

from continuiti.data.function import FunctionSet

sine_set = FunctionSet(lambda a: Function(lambda x: a[0] * torch.sin(a[1] * torch.pi * x)))

parameters = 5 * torch.rand(2, 4)  # 2 parameters in 4 sets

sines = sine_set(parameters)
No description has been provided for this image

Sampler

In continuiti, there are samplers to create discrete representations of continuous functions. The following example shows how the RegularGridSampler and the UniformBoxSampler handle this. Both take two corner points of a \(n\)-dimensional rectangle as inputs.

from continuiti.discrete import RegularGridSampler, UniformBoxSampler

sampler_a = RegularGridSampler([1., 1.], [1.5, 2.5])
sampler_b = UniformBoxSampler([1.75, 1.25], [3., 1.75])

n_samples = 102
samples_a = sampler_a(n_samples)
samples_b = sampler_b(n_samples)

print(f"Shape of sample A: {samples_a.shape} (as 6 x 17 = 102), Shape of sample B: {samples_b.shape}")
Shape of sample A: torch.Size([2, 6, 17]) (as 6 x 17 = 102), Shape of sample B: torch.Size([2, 102])

No description has been provided for this image

Now, we can use these samplers to draw samples from our previously defined sine wave \(y = \beta \sin(k\pi x)\). In a first step, we will draw from the parameter space. In a second step, we draw from the domain.

parameter_sampler = RegularGridSampler([1., 1.], [2., 2.])
domain_sampler = UniformBoxSampler([-1.], [1.])

# sample parameter space
n_parameter_samples = 9
parameter_samples = parameter_sampler(n_parameter_samples).reshape(2, -1)
sines = sine_set(parameter_samples)

# sample domain
n_sensors = 32
x = []
y = []
for sine in sines:
    xi = domain_sampler(n_sensors)
    x.append(xi)
    yi = sine(xi)
    y.append(yi)
x = torch.stack(x)
y = torch.stack(y)
No description has been provided for this image

Function Operator Datasets

In continuiti, the concepts of function sets and samplers are combined to form FunctionOperatorDataset instances. This class is used to handle scenarios where both the input function set \(U\) and the output function set \(V\) of an operator \(G\) are known. It utilizes samplers to generate samples to generate a training set.

Note

The FunctionOperatorDataset assumes that both function sets are defined on the same parameters.

In this example, we show how to generate a derivative operator dataset $$ G:u\mapsto \partial_x u, $$ for the parameterized sine function $$ u_a: x\mapsto \sin(ax), \quad a, x\in \mathbb{R}, $$ and its derivative $$ v_a: x\mapsto a\cos(ax), \quad a,x \in \mathbb{R}. $$

from continuiti.data.function import FunctionOperatorDataset

u_set = FunctionSet(lambda a: Function(lambda xi: torch.sin(a * xi)))
v_set = FunctionSet(lambda a: Function(lambda xi: a * torch.cos(a * xi)))

x_sampler = RegularGridSampler([-1], [1.])
y_sampler = UniformBoxSampler([-2], [.5])
parameter_sampler = RegularGridSampler([torch.pi], [2 * torch.pi])

dset = FunctionOperatorDataset(
    input_function_set=u_set,
    x_sampler=x_sampler,
    n_sensors=64,
    output_function_set=v_set,
    y_sampler=y_sampler,
    n_evaluations=128,
    parameter_sampler=parameter_sampler,
    n_observations=4,
)
No description has been provided for this image

Last update: 2024-08-20
Created: 2024-08-20