# Terms

Terms specify how a node variable is build from its parents.

## Usage

Here is how a term can be setup

```
from bn_testing.terms import Term
import numpy as np
some_term = Term(
parents=['a', 'b'],
term_fn=lambda v: np.sqrt(v['a'])*v['b'],
)
```

Afterwards, the term can be applied on `pymc`

variables and
distributions:

```
import pymc as pm
dist = some_term(
a=pm.Normal.dist(mu=1, sigma=0.4),
b=pm.Beta.dist(alpha=0.4, beta=0.2),
)
```

## Existing terms

Here is a list of terms that ease instantiation for some classes of terms frequently used. Assume that the parents are \(x_1,\ldots,x_n\):

`Linear`

: A linear term of the form \(\sum_{i=1}^nw_ix_i\)`Polynomial`

: A multivariate polynomial, i.e., a sum of the form \(\sum_{j=1}^mc_j\prod_{i=1}^nx_i^{e_{ji}}\)

## Arithmetic with terms

Given two terms `term_a`

and `term_b`

, another term can be
constructed by applying a basic arithemtic computation. For instance:

```
term_a + term_b
term_a * term_b
(2 * term_a + 3 * term_b)**10
```

Note

Composing terms like `term_a(term_b)`

is currently not
supported.

## Implementing own terms

Typically, new terms can be formed by combining the basic terms.

Here is a small example how a term can be computed:

```
from bn_testing.terms import Term
import numpy as np
class RootMeanSquared(Term):
def __init__(self, parents):
super(OwnTerm, self).__init__(parents=parents)
def apply(self, parents_mapping):
parents = self.get_vars_from_dict(parents_mapping)
return np.sqrt(np.mean(parents**2))
```

Note

Generally, `Terms`

are generated by
`Conditionals`

and the parents
are selected at runtime randomly. Terms, however, should be
deterministic and any random selections should be done in the
calling `Conditionals`

.