# Interventions

Given a `bn_testing.models.Model`

object, modifications,
like interventions, of the terms and source distributions can be
applied and data from the modified model can be sampled.

The goal of these modificiations may be:

Generating interventional data.

Simulation of changed behavior in the system under study.

## Apply Modifications

Assume that `model`

represents a additive structural equation
model with DAG \(G\) and equations

Generally, modifications are changes of the transformations \(f_i\) and the additive noise \(\epsilon_i\).

Assume we have given a `model`

having a node Assume a node
\(X_3\) with parents \(X_1\) and \(X_2\) and \(f_3(x_1,
x_2)=x_1^2\cdot x_2+x_1\) and \(\epsilon_3\sim\mathcal{N}(0, 1)\).
That means,

### Randomized modification

One way to change the construction of \(X_3\) from its parents is
by randomly generating a new `Term`

and additive noise object using the `Conditional`

used
when instantiating the model. This can be done as folllows:

```
model.modify_node(node='X3')
```

The same works for source nodes, where a new source distribution is
generated using the
`make_source()`

method of
the condidtional object.

Note

The model modification is done inplace, that means, an applied modification cannot be undone.

Alternatively, the new term can also be generated using another conditional:

```
from bn_testing.conditionals import LinearConditional
model.modify_node(node='X3', conditionals=LinearConditional())
```

Note

A modification not only changes the term, but also the additive noise!

### Controlled modification

#### Inner nodes

Instead of randomly generating a new term for \(X_3\) is constructed, we can also directly set the new term:

```
from bn_testing.terms import Linear
import pymc as pm
model.modify_inner_node(
node='X3',
term=Linear(['X1', 'X2'], [0.5, -0.1],
noise=pm.Beta.normal(alpha=0.2, beta=0.1),
)
```

Note that if either the `noise`

or the `term`

are omitted,
a respective object is generated using the
`Conditional`

given when
instantiating the model.

#### Source nodes

If \(X1\) is a source node, its distribution can be replaced with another distribution as follows:

```
import pymc as pm
model.modify_source_node(
node='X3',
distribution=pm.Beta.dist(alpha=0.9, beta=0.1),
)
```

## Computing causal effects

A special case of a modification is when a random variable is set to a constant value. Typically, this is done because the average causal effect of \(X_i\) having value \(k\) onto another variable, like \(X_j\) should be determined. This is

In our example above, setting \(X_1=2\) permantently can be archived with:

```
from bn_testing.conditionals import ConstantConditional
import pymc as pm
model.modify_node(
node='X1',
conditionals=ConstantConditional(2)
)
```

The average causal effect for this setting can be computed using the
shortcut `compute_average_causal_effect()`

:

```
model.compute_average_causal_effect(
node_from='X1',
node_onto='X3',
value=2,
)
```

Note

The calculation of the expected values used in the formula of the
average causal effect is done empirically by sampling from the
model with and without modification. The number of samples used can
be changed by setting the paramater `n`

.