Skip to content
Open
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
4 changes: 4 additions & 0 deletions src/Bridges/Bridges.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
module Bridges

import MathOptInterface as MOI
using PolyJuMP

include("Utilities.jl")
# Constraint bridges
include("Constraint/Constraint.jl")
# Objective bridges
Expand Down
1 change: 1 addition & 0 deletions src/Bridges/Constraint/Constraint.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ include("zero_polynomial.jl")
include("zero_polynomial_in_algebraic_set.jl")
include("plus_minus.jl")
include("to_polynomial.jl")
include("to_reformulated_polynomial.jl")

end # module
79 changes: 79 additions & 0 deletions src/Bridges/Constraint/to_reformulated_polynomial.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
"""
ToReformulatedPolynomialBridge{T,S} <: Bridges.Constraint.AbstractBridge

`ToReformulatedPolynomialBridge` implements a sparsity-preserving
reformulation of `f(x) in S` into `g(x, y) in S` where `f` is a
`MOI.ScalarNonlinearFunction`: products and powers of sums are replaced by
auxiliary variables `y`, so that converting `g` into a polynomial does not
expand them.

Since source and target are both `MOI.ScalarNonlinearFunction`, this bridge
doesn't have any effect when added to a `MOI.Bridges.LazyBridgeOptimizer`; use it in a
`MOI.Bridges.Constraint.SingleBridgeOptimizer` on top of an optimizer converting
`MOI.ScalarNonlinearFunction` into polynomials, e.g., [`PolyJuMP.QCQP.Optimizer`](@ref).

## Source node

`ToReformulatedPolynomialBridge` supports:

* `MOI.ScalarNonlinearFunction` in `S`

## Target nodes

`ToReformulatedPolynomialBridge` creates:

* `MOI.ScalarNonlinearFunction` in `S`
* `MOI.ScalarNonlinearFunction` in `MOI.EqualTo{T}`, defining the
auxiliary variables
* `MOI.VariableIndex` in `MOI.Interval{T}`, the auxiliary variables
"""
struct ToReformulatedPolynomialBridge{T,S} <:
MOI.Bridges.Constraint.AbstractFunctionConversionBridge{MOI.ScalarNonlinearFunction,S}
constraint::MOI.ConstraintIndex{MOI.ScalarNonlinearFunction,S}
end

function MOI.Bridges.Constraint.bridge_constraint(
::Type{ToReformulatedPolynomialBridge{T,S}},
model::MOI.ModelLike,
func::MOI.ScalarNonlinearFunction,
set::S,
) where {T,S}
reformulated = PolyJuMP.Bridges._to_reformulated_polynomial!(model, T, func)
constraint = MOI.add_constraint(model, reformulated, set)
return ToReformulatedPolynomialBridge{T,S}(constraint)
end

function MOI.Bridges.Objective.supports_objective_function(
::Type{ToReformulatedPolynomialBridge{T}},
::Type{F},
) where {T,F<:MOI.ScalarNonlinearFunction}
return MOI.Utilities.is_coefficient_type(F, T)
end


function MOI.supports_constraint(
::Type{ToReformulatedPolynomialBridge{T}},
::Type{MOI.ScalarNonlinearFunction},
::Type{<:MOI.AbstractScalarSet},
) where {T}
return true
end

function MOI.Bridges.Constraint.concrete_bridge_type(
::Type{<:ToReformulatedPolynomialBridge{T}},
::Type{MOI.ScalarNonlinearFunction},
::Type{S},
) where {T,S<:MOI.AbstractScalarSet}
return ToReformulatedPolynomialBridge{T,S}
end


function MOI.get(
model::MOI.ModelLike,
attr::MOI.Bridges.ObjectiveFunctionValue,
::ToReformulatedPolynomialBridge{T},
) where {T}
F = FuncType{T}
attr_f = MOI.Bridges.ObjectiveFunctionValue{F}(attr.result_index)
return MOI.get(model, attr_f)
end
4 changes: 2 additions & 2 deletions src/Bridges/Objective/Objective.jl
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
module Objective

import MathOptInterface
const MOI = MathOptInterface
import MathOptInterface as MOI

using PolyJuMP

include("to_polynomial.jl")
include("to_reformulated_polynomial.jl")

end # module
58 changes: 58 additions & 0 deletions src/Bridges/Objective/to_reformulated_polynomial.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
"""
ToReformulatedPolynomialBridge{T} <: Bridges.Objective.AbstractBridge

`ToReformulatedPolynomialBridge` implements a sparsity-preserving
reformulation of the objective `f(x)` into `g(x, y)` where `f` is a
`MOI.ScalarNonlinearFunction`: products and powers of sums are replaced by
auxiliary variables `y`, so that converting `g` into a polynomial does not
expand them.

Since source and target are both `MOI.ScalarNonlinearFunction`, this bridge
doesn't have any effect when added to a `MOI.Bridges.LazyBridgeOptimizer`; use it in a
`MOI.Bridges.Objective.SingleBridgeOptimizer` on top of an optimizer converting
`MOI.ScalarNonlinearFunction` into polynomials, e.g., [`PolyJuMP.QCQP.Optimizer`](@ref).

## Source node

`ToReformulatedPolynomialBridge` supports:

* `MOI.ObjectiveFunction{MOI.ScalarNonlinearFunction}`

## Target nodes

`ToReformulatedPolynomialBridge` creates:

* `MOI.ObjectiveFunction{MOI.ScalarNonlinearFunction}`
* `MOI.ScalarNonlinearFunction` in `MOI.EqualTo{T}`, defining the auxiliary
variables
* `MOI.VariableIndex` in `MOI.Interval{T}`, the auxiliary variables
"""
struct ToReformulatedPolynomialBridge{T} <: MOI.Bridges.Objective.AbstractBridge end

function MOI.Bridges.Objective.bridge_objective(
::Type{ToReformulatedPolynomialBridge{T}},
model::MOI.ModelLike,
func::MOI.ScalarNonlinearFunction,
) where {T}
reformulated = PolyJuMP.Bridges._to_reformulated_polynomial!(model, T, func)
F = MOI.ScalarNonlinearFunction
MOI.set(model, MOI.ObjectiveFunction{F}(), reformulated)
return ToReformulatedPolynomialBridge{T}()
end

function MOI.Bridges.Objective.supports_objective_function(
::Type{ToReformulatedPolynomialBridge{T}},
::Type{F},
) where {T,F<:MOI.ScalarNonlinearFunction}
return MOI.Utilities.is_coefficient_type(F, T)
end

function MOI.get(
model::MOI.ModelLike,
attr::MOI.Bridges.ObjectiveFunctionValue,
::ToReformulatedPolynomialBridge{T},
) where {T}
F = FuncType{T}
attr_f = MOI.Bridges.ObjectiveFunctionValue{F}(attr.result_index)
return MOI.get(model, attr_f)
end
Loading
Loading