# Encodings for multi-shot solving

This section gives an overview of the encodings for solving an instance with unbounded cardinalities using multi-shot solving.
These encodings mostly just reorganize the main [COOM encoding][coom-encoding] into specific program parts for multi-shot solving.

For example usage information see the [Cargo bike example][cargo-bike].

[coom-encoding]: ../index.md
[cargo-bike]: ../../examples/cargo-bike.md

We start by explaining some general concepts using a simplified version of the [Cargo bike][cargo-bike] example.

```cpp
product {
         num 0-20 numBags
    0..* Bag      bags
}

structure Bag {
    Color color
}

enumeration Color { Red Blue }

behavior {
    require numBags = count(bags)
}

behavior Bag {
    require color = Blue
}
```

[cargo-bike]: ../../../examples/cargo-bike.md

## Preprocessing

The preprocessing removes the cardinality on `Bags` by instatiating a number of bags based on the `max_bound` parameter of the preprocessing encoding.
Using one of the `bounds` strategies we step-wise increase this parameter until a solution is found.

To avoid regrounding and resolving the same part of a problem over and over, we employ multi-shot solving here:
we add the new facts generated by the preprocessing of a new `max_bound` as new program parts.

The facts added by a new step of the preprocessing can be divided into two groups: object and constraint facts.

## Object Facts

Facts of the first group are the predicates `parent`, `index`, `set`, and `type` describing a new object.
These are added through respective program parts in the [new object][new-object] encoding.

[new-object]: new-object.md

## Constraint Facts

The second group of facts is made up of facts describing new constraints as well as their components (i.e. binaries, unaries, and functions).
The constraints (and their components) are further divided into two categories: simple constraints and incremental constraints.

### Simple Constraints

An example for a simple constraint is the constraint on the `color` of a `Bag`.
This constraint will be added for each new instance of `Bag` but is not affected by the addition of further instances later on.
The additions of this kind of constraint (and its components) is handled by the [new simple constraint encodings][simple-constraint]

[simple-constraint]: simple-constraint.md

### Incremental Constraints

An example for an incremental constraint is the constraint on `numBags`: it uses a `count` aggregate over all instances of `Bag`.
This constraint is added once (at the beginning) but its evaluation changes over time:
with each step of the preprocessing new instances of `Bag` are added and need to be taken into account when evaluating this constraint.
These kinds of constraint (and their components) are handled by the [new incremental constraint encodings][incremental-constraint]

Note that also a table constraint can be incremental.
Consider the following example.

```cpp
product {
    0..* Bag      bags
}

structure Bag {
         Color color
    0..* Pocket pockets
}

enumeration Color { Red Blue }

enumeration Pocket { Small Large }

behavior Bag {
    combinations (color pockets)
    allow        (Red   Small  )
    allow        (Blue  Large  )
}
```

With `max_bound` of 1, a first instance of the table constraint is added constraining `bags[0].pockets[0]`.
When the `max_bound` is increased to 2 a new instance of the same table is added constraining `bags[0].pockets[1]`.
The different instantiations of a table are distinguished by the second argument of the `column/4` predicate.
However, note that each instance of the table constraints itself behaves like a simple constraint from above.
This is used in the evaluation of incremental constraints in the respective [encoding][incremental-table].

[incremental-constraint]: incremental-constraint.md
[incremental-table]: incremental-constraint.md#encodings

## Multi-Shot Specific Preprocessing

The classification of which constraints and expressions are incremental is handled by a [multi-shot specific addition][multi-preprocessing] to the preprocessing encoding.

[multi-preprocessing]: preprocessing.md

## Extending the Input Language

This section gives a general workflow for updating the multishot encoding for extensions of the input language.

For any new predicates produced by the preprocessing new programs parts are needed analogous to the [new object][new-object] and [new simple constraint][simple-constraint] encodings.
Usually these encodings are just the respective rules from the single shot approach encapsulated into a new program part.
The arguments of the new predicate correspond to the arguments of the new program part.
This is not necessary if new facts over the new predicate can only be produced by the initial preprocessing step.

Additionally, the [multi-shot specific preprocessing][multishot-preprocessing] may need to be updated for new predicates.
This is the case if the new predicate produces incremental constraints or may be included in existing incremental constraints (see above).
The preprocessing then needs to be extended to detect those cases.
(Here it is important to keep the edge case of a cardinality `0..*` with `max_bound=0` in mind.)
It is then also necessary to add new incremental program parts analogous to the [new incremental constraint][incremental-constraint] and [new incremental table][incremental-table] encodings.

[multishot-preprocessing]: #multi-shot-specific-preprocessing

Finally, the [python implementation][multi-application] needs to be updated.

[multi-application]: ../../python/bounds/multi_application.md#extending-the-input-language
