> ## Documentation Index
> Fetch the complete documentation index at: https://docs.activeviam.com/llms.txt
> Use this file to discover all available pages before exploring further.

# What-If

The What-If feature allows users to simulate a change of a subset of their data without modifying
the production data.
For instance, a user might want to change risk data and configuration parameters to evaluate their
impact on the capital.

As capital is a non-linear calculation, it can be difficult to predict the
impact of a small change simply with a mind experiment. At this point, the user might need to
recompute the capital with the modified data to evaluate the impact of the changes.

What-If allows the user to visualize this impact by creating an experimental
version, called a **branch**, and specify the required data changes. The production data (the master
branch) remains intact, so other users still see the production
data. For the user experimenting with "what-if" changes, switching back to production data is
simple, and the results of the experiment can be shared easily.

What-If is also available in a distributed setup.

> This feature is not about *distributed transactions*, which would allow you to create a branch from a
> query cube and commit data to each data cube.

## Principle

Starting a simulation in a data cube creates a new branch.\
If it is connected to a cluster with a query node, the latter detects the new branch and also creates a new version, which targets the branch with the corresponding name in the data cube.
If another data cube creates another scenario, another branch appears in the query cube, and so on.
The query cube's branches are the union of all the data cubes' branches.

> Please be aware that this induces more network traffic within your application.

## Querying for Distributed Branches

A query cube that has detected several branches applies the following logic when treating a query:

* if the branch exists in the data cube, the query is performed on that branch.
* if the branch does not exist in the data cube, the query is performed on the *master* branch.

For example, query cube Q has two underlying data cubes: A and B.
Data cube A defines the branches *master* and *scenario*. Data cube B has branches *master* and
*test*.
They contain the following data:

| Currency    | Cube A *master* | Cube A *scenario* | Cube B *master* | Cube B *test* |
| ----------- | --------------- | ----------------- | --------------- | ------------- |
| Grand total | 12              | 13                | 22              | 1             |
| BTC         | 1               | 1                 |                 |               |
| EUR         | 1               | 3                 | 6               | 1             |
| USD         | 2               | 4                 |                 |               |
| JPY         |                 | 5                 |                 |               |
| GBP         | 8               |                   | 7               |               |
| CHF         |                 |                   | 9               |               |

Running the query for branch *scenario* on the query cube results in the following table:

| Currency    | Measure |
| ----------- | ------- |
| Grand total | 35      |
| BTC         | 1       |
| EUR         | 9       |
| USD         | 4       |
| JPY         | 5       |
| GBP         | 7       |
| CHF         | 9       |

The following changes occur:

* EUR is modified in branch *scenario*, so the value is the aggregation of this modified value
  with the unmodified value from cube B.
* JPY, present in data cube A for branch *scenario*, is present in the result. This currency is expected to appear in the query if in the
  scenario, the company acquires some JPY.
* GBP, only present in data cube B for branch *master*, has a value of 7 because it does not exist
  in data cube A for the branch *scenario*.
* BTC's value did not change in the branch *scenario*, and the result's value stays the same.

## Configuration

To activate the epoch dimension in a query node, you have to enable it in the query cube description
like this:

```
builder
    .asQueryCube()
        .withClusterDefinition()
        ...
        .end()
    .withEpochDimension()
    ...
```

The description looks like this:

```java theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
return StartBuilding.cube(CUBE_NAME)
    .withCalculations(
        c -> {
          Copper.count().withinFolder(NATIVE_MEASURES).withFormatter(INT_FORMATTER).publish(c);
          Copper.timestamp()
              .withinFolder(NATIVE_MEASURES)
              .withFormatter(TIMESTAMP_FORMATTER)
              .publish(c);
        })
    .asQueryCube()
    .withClusterDefinition()
    .withClusterId(CLUSTER_ID)
    .withMessengerDefinition()
    .withProtocolPath("jgroups-protocols/protocol-tcp.xml")
    .end()
    .withApplication(APPLICATION_ID)
    .withDistributingLevels(new LevelIdentifier("Time", "HistoricalDates", "AsOfDate"))
    .end()
    .withEpochDimension()
```
