Skip to content

[docs] add more docs for implementing a bridge #2334

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Nov 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ const _PAGES = [
],
"Bridges" => [
"Overview" => "submodules/Bridges/overview.md",
"Implementation" => "submodules/Bridges/implementation.md",
"List of bridges" => "submodules/Bridges/list_of_bridges.md",
"API Reference" => "submodules/Bridges/reference.md",
],
Expand Down
123 changes: 123 additions & 0 deletions docs/src/submodules/Bridges/implementation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
```@meta
CurrentModule = MathOptInterface
DocTestSetup = quote
import MathOptInterface as MOI
end
DocTestFilters = [r"MathOptInterface|MOI"]
```

# Implementing a bridge

The easiest way to implement a bridge is to follow an existing example. There
are three locations of bridges in the source code:

* Constraint bridges are stored in `src/Bridges/Constraint/bridges`
* Objective bridges are stored in `src/Bridges/Objective/bridges`
* Variable bridges are stored in `src/Bridges/Variable/bridges`

The [Implementing a constraint bridge](@ref) tutorial has a more detailed guide
on what is required to implement a bridge.

When opening a pull request that adds a new bridge, use the checklist
[Adding a new bridge](@ref).

If you need help or advice, please contact the [Developer Chatroom](https://jump.dev/chatroom/).

## SetMap bridges

For constraint and variable bridges, a common reformulation is that ``f(x) \in F``
is reformulated to ``g(x) \in G``. In this case, no additional variables and
constraints are added, and the bridge needs only a way to map between the
functions `f` and `g` and the sets `F` and `G`.

To implementation a bridge of this form, subtype the abstract type
[`Bridges.Constraint.SetMapBridge`](@ref) or
[`Bridges.Variable.SetMapBridge`](@ref) and implement the API described in the
docstring of each type.

## `final_touch`

Some bridges require information from other parts of the model. One set of
examples are the various combinatorial `ToMILP` bridges, such as
[`Bridges.Constraint.SOS1ToMILPBridge`](@ref), which require knowledge of the
variable bounds.

Bridges requiring information from other parts of the model should implement
[`Bridges.final_touch`](@ref) and [`Bridges.needs_final_touch`](@ref).

During the bridge's construction, store the function and set and make no changes
to the underlying model. Then, in [`Bridges.final_touch`](@ref), query the
additional information and add the reformulated problem to the `model`.

When implementing, you must consider that:

* [`Bridges.final_touch`](@ref) may be called multiple times, so that your
reformulation should be applied only if necessary. Sometimes the additional
data will be the same, and sometimes it may be different.
* We do not currently support `final_touch` bridges that introduce constraints
which also require a `final_touch` bridge. Therefore, you should implement
`final_touch` only if necessary, and we recommend that you contact the
[Developer Chatroom](https://jump.dev/chatroom/) for advice before doing so.

## Testing

Use the [`Bridges.runtests`](@ref) function to test a bridge. It takes three
arguments: the type of the bridge, the input model as a string, and the output
model as a string.

Here is an example:
```jldoctest
julia> MOI.Bridges.runtests(
MOI.Bridges.Constraint.GreaterToLessBridge,
"""
variables: x
x >= 1.0
""",
"""
variables: x
-1.0 * x <= -1.0
""",
)
```

There are a number of other useful keyword arguments.

* `eltype` can be used to specify the element type of the model (and bridge).
It defaults to `Float64`.
* `variable_start` and `constraint_start` are used as the values to set the
[`VariablePrimalStart`](@ref) and [`ConstraintPrimalStart`](@ref) attributes
to. They default to `1.2`. If you use a different `eltype`, you must set
appropriate starting values of the same type. The default `1.2` was chosen to
minimize the risk that the starting point is undefined, which could happen
for common situations like `0.0` and `1.0`. The tests associated with the
starting values do not necessarily check for correctness, only that they can
be `set` and `get` to produce the same result.
* `print_inner_model` can be used to print the reformulated output model from
the bridge. This is especially helpful during debugging to see what the
bridge is doing, and to spot mistakes. It defaults to `false`.

Here is an example:

```jldoctest
julia> MOI.Bridges.runtests(
MOI.Bridges.Constraint.GreaterToLessBridge,
"""
variables: x
x >= 1
""",
"""
variables: x
::Int: -1 * x <= -1
""";
eltype = Int,
print_inner_model = true,
variable_start = 2,
constraint_start = 2,
)
Feasibility

Subject to:

ScalarAffineFunction{Int64}-in-LessThan{Int64}
(0) - (1) x <= (-1)
```
1 change: 1 addition & 0 deletions docs/src/submodules/Bridges/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ get(::Bridges.AbstractBridge, ::ListOfConstraintIndices)
Bridges.needs_final_touch
Bridges.final_touch
Bridges.bridging_cost
Bridges.runtests
```

## Constraint bridge API
Expand Down
1 change: 1 addition & 0 deletions docs/src/submodules/Utilities/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ Utilities.default_copy_to
Utilities.IndexMap
Utilities.identity_index_map
Utilities.ModelFilter
Utilities.loadfromstring!
```

## Penalty relaxation
Expand Down