Problem modification
In addition to adding and deleting constraints and variables, MathOptInterface supports modifying, in-place, coefficients in the constraints and the objective function of a model.
These modifications can be grouped into two categories:
- modifications which replace the set of function of a constraint with a new set or function
- modifications which change, in-place, a component of a function
Some ModelLike
objects do not support problem modification.
Modify the set of a constraint
Use set
and ConstraintSet
to modify the set of a constraint by replacing it with a new instance of the same type.
julia> c = MOI.add_constraint(
model,
MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x)], 0.0),
MOI.EqualTo(1.0),
)
MathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.EqualTo{Float64}}(1)
julia> MOI.set(model, MOI.ConstraintSet(), c, MOI.EqualTo(2.0));
julia> MOI.get(model, MOI.ConstraintSet(), c) == MOI.EqualTo(2.0)
true
However, the following will fail as the new set is of a different type to the original set:
julia> MOI.set(model, MOI.ConstraintSet(), c, MOI.GreaterThan(2.0))
ERROR: [...]
Special cases: set transforms
If our constraint is an affine inequality, then this corresponds to modifying the right-hand side of a constraint in linear programming.
In some special cases, solvers may support efficiently changing the set of a constraint (for example, from LessThan
to GreaterThan
). For these cases, MathOptInterface provides the transform
method.
The transform
function returns a new constraint index, and the old constraint index (that is, c
) is no longer valid.
julia> c = MOI.add_constraint(
model,
MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x)], 0.0),
MOI.LessThan(1.0),
)
MathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.LessThan{Float64}}(1)
julia> new_c = MOI.transform(model, c, MOI.GreaterThan(2.0));
julia> MOI.is_valid(model, c)
false
julia> MOI.is_valid(model, new_c)
true
Modify the function of a constraint
Use set
and ConstraintFunction
to modify the function of a constraint by replacing it with a new instance of the same type.
julia> c = MOI.add_constraint(
model,
MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x)], 0.0),
MOI.EqualTo(1.0),
)
MathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.EqualTo{Float64}}(1)
julia> new_f = MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(2.0, x)], 1.0);
julia> MOI.set(model, MOI.ConstraintFunction(), c, new_f);
julia> MOI.get(model, MOI.ConstraintFunction(), c) ≈ new_f
true
However, the following will fail as the new function is of a different type to the original function:
julia> MOI.set(model, MOI.ConstraintFunction(), c, x)
ERROR: [...]
Modify constant term in a scalar function
Use modify
and ScalarConstantChange
to modify the constant term in a ScalarAffineFunction
or ScalarQuadraticFunction
.
julia> c = MOI.add_constraint(
model,
MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x)], 0.0),
MOI.EqualTo(1.0),
)
MathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.EqualTo{Float64}}(1)
julia> MOI.modify(model, c, MOI.ScalarConstantChange(1.0));
julia> new_f = MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x)], 1.0);
julia> MOI.get(model, MOI.ConstraintFunction(), c) ≈ new_f
true
ScalarConstantChange
can also be used to modify the objective function by passing an instance of ObjectiveFunction
:
julia> MOI.set(
model,
MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(),
new_f,
);
julia> MOI.modify(
model,
MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(),
MOI.ScalarConstantChange(-1.0)
);
julia> MOI.get(
model,
MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(),
) ≈ MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x)], -1.0)
true
Modify constant terms in a vector function
Use modify
and VectorConstantChange
to modify the constant vector in a VectorAffineFunction
or VectorQuadraticFunction
.
julia> c = MOI.add_constraint(
model,
MOI.VectorAffineFunction([
MOI.VectorAffineTerm(1, MOI.ScalarAffineTerm(1.0, x)),
MOI.VectorAffineTerm(2, MOI.ScalarAffineTerm(2.0, x)),
],
[0.0, 0.0],
),
MOI.Nonnegatives(2),
)
MathOptInterface.ConstraintIndex{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Nonnegatives}(1)
julia> MOI.modify(model, c, MOI.VectorConstantChange([3.0, 4.0]));
julia> new_f = MOI.VectorAffineFunction(
[
MOI.VectorAffineTerm(1, MOI.ScalarAffineTerm(1.0, x)),
MOI.VectorAffineTerm(2, MOI.ScalarAffineTerm(2.0, x)),
],
[3.0, 4.0],
);
julia> MOI.get(model, MOI.ConstraintFunction(), c) ≈ new_f
true
Modify affine coefficients in a scalar function
Use modify
and ScalarCoefficientChange
to modify the affine coefficient of a ScalarAffineFunction
or ScalarQuadraticFunction
.
julia> c = MOI.add_constraint(
model,
MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x)], 0.0),
MOI.EqualTo(1.0),
)
MathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.EqualTo{Float64}}(1)
julia> MOI.modify(model, c, MOI.ScalarCoefficientChange(x, 2.0));
julia> new_f = MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(2.0, x)], 0.0);
julia> MOI.get(model, MOI.ConstraintFunction(), c) ≈ new_f
true
ScalarCoefficientChange
can also be used to modify the objective function by passing an instance of ObjectiveFunction
.
Modify quadratic coefficients in a scalar function
Use modify
and ScalarQuadraticCoefficientChange
to modify the quadratic coefficient of a ScalarQuadraticFunction
.
julia> model = MOI.Utilities.Model{Float64}();
julia> x = MOI.add_variables(model, 2);
julia> c = MOI.add_constraint(
model,
1.0 * x[1] * x[1] + 2.0 * x[1] * x[2],
MOI.EqualTo(1.0),
)
MathOptInterface.ConstraintIndex{MathOptInterface.ScalarQuadraticFunction{Float64}, MathOptInterface.EqualTo{Float64}}(1)
julia> MOI.modify(
model,
c,
MOI.ScalarQuadraticCoefficientChange(x[1], x[1], 3.0),
);
julia> MOI.modify(
model,
c,
MOI.ScalarQuadraticCoefficientChange(x[1], x[2], 4.0),
);
julia> new_f = 1.5 * x[1] * x[1] + 4.0 * x[1] * x[2];
julia> MOI.get(model, MOI.ConstraintFunction(), c) ≈ new_f
true
ScalarQuadraticCoefficientChange
can also be used to modify the objective function by passing an instance of ObjectiveFunction
.
Modify affine coefficients in a vector function
Use modify
and MultirowChange
to modify a vector of affine coefficients in a VectorAffineFunction
or a VectorQuadraticFunction
.
julia> c = MOI.add_constraint(
model,
MOI.VectorAffineFunction([
MOI.VectorAffineTerm(1, MOI.ScalarAffineTerm(1.0, x)),
MOI.VectorAffineTerm(2, MOI.ScalarAffineTerm(2.0, x)),
],
[0.0, 0.0],
),
MOI.Nonnegatives(2),
)
MathOptInterface.ConstraintIndex{MathOptInterface.VectorAffineFunction{Float64}, MathOptInterface.Nonnegatives}(1)
julia> MOI.modify(model, c, MOI.MultirowChange(x, [(1, 3.0), (2, 4.0)]));
julia> new_f = MOI.VectorAffineFunction(
[
MOI.VectorAffineTerm(1, MOI.ScalarAffineTerm(3.0, x)),
MOI.VectorAffineTerm(2, MOI.ScalarAffineTerm(4.0, x)),
],
[0.0, 0.0],
);
julia> MOI.get(model, MOI.ConstraintFunction(), c) ≈ new_f
true