Skip to content

Commit a493c68

Browse files
committed
Fix
1 parent 0beeb0c commit a493c68

File tree

1 file changed

+94
-141
lines changed

1 file changed

+94
-141
lines changed

src/Utilities/model.jl

Lines changed: 94 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ end
153153

154154
function MOI.get(model::AbstractModel, ::MOI.ListOfVariableAttributesSet)
155155
ret = MOI.AbstractVariableAttribute[]
156-
if isempty(model.var_to_name)
156+
if !isempty(model.var_to_name)
157157
push!(ret, MOI.VariableName())
158158
end
159159
return ret
@@ -608,14 +608,12 @@ function _struct_of_constraints_type(name, subtypes, parametrized_type)
608608
if length(subtypes) == 1
609609
# Only one type, no need for a `StructOfConstraints`.
610610
return subtypes[1]
611-
else
612-
T = esc(:T)
613-
t = :($name{$T})
614-
if parametrized_type
615-
append!(t.args, subtypes)
616-
end
617-
return t
618611
end
612+
expr = Expr(:curly, name, esc(:T))
613+
if parametrized_type
614+
append!(expr.args, subtypes)
615+
end
616+
return expr
619617
end
620618

621619
# This macro is for expert/internal use only. Prefer the concrete Model type
@@ -634,155 +632,96 @@ end
634632
is_optimizer = false
635633
)
636634
637-
Creates a type `model_name` implementing the MOI model interface and containing
638-
`scalar_sets` scalar sets `typed_scalar_sets` typed scalar sets, `vector_sets`
639-
vector sets, `typed_vector_sets` typed vector sets, `scalar_functions` scalar
640-
functions, `typed_scalar_functions` typed scalar functions, `vector_functions`
641-
vector functions and `typed_vector_functions` typed vector functions.
642-
To give no set/function, write `()`, to give one set `S`, write `(S,)`.
643-
644-
The function [`MOI.VariableIndex`](@ref) should not be given in
645-
`scalar_functions`. The model supports [`MOI.VariableIndex`](@ref)-in-`S`
646-
constraints where `S` is [`MOI.EqualTo`](@ref),
647-
[`MOI.GreaterThan`](@ref), [`MOI.LessThan`](@ref),
648-
[`MOI.Interval`](@ref), [`MOI.Integer`](@ref),
649-
[`MOI.ZeroOne`](@ref), [`MOI.Semicontinuous`](@ref)
650-
or [`MOI.Semiinteger`](@ref). The sets supported
651-
with the [`MOI.VariableIndex`](@ref) cannot be controlled from the
652-
macro, use the [`UniversalFallback`](@ref) to support more sets.
653-
654-
This macro creates a model specialized for specific types of constraint,
655-
by defining specialized structures and methods. To create a model that,
656-
in addition to be optimized for specific constraints, also support arbitrary
657-
constraints and attributes, use [`UniversalFallback`](@ref).
658-
659-
If `is_optimizer = true`, the resulting struct is a
660-
of [`GenericOptimizer`](@ref), which is a subtype of
661-
[`MOI.AbstractOptimizer`](@ref), otherwise, it is a
662-
[`GenericModel`](@ref), which is a subtype of
663-
[`MOI.ModelLike`](@ref).
664-
665-
### Examples
666-
667-
The model describing an linear program would be:
668-
```julia
669-
@model(LPModel, # Name of model
670-
(), # untyped scalar sets
671-
(MOI.EqualTo, MOI.GreaterThan, MOI.LessThan, MOI.Interval), # typed scalar sets
672-
(MOI.Zeros, MOI.Nonnegatives, MOI.Nonpositives), # untyped vector sets
673-
(), # typed vector sets
674-
(), # untyped scalar functions
675-
(MOI.ScalarAffineFunction,), # typed scalar functions
676-
(MOI.VectorOfVariables,), # untyped vector functions
677-
(MOI.VectorAffineFunction,), # typed vector functions
678-
false
679-
)
680-
```
635+
Creates a type `model_name` implementing the MOI model interface and supporting
636+
all combinations of the provided functions and sets.
637+
638+
Each `typed_` `scalar`/`vector` `sets`/`functions` argument is a tuple of types.
639+
A type is "typed" if it has a coefficient `{T}` as the first type parameter.
640+
641+
## Tuple syntax
642+
643+
To give no set/function, write `()`.
644+
To give one set or function `X`, write `(X,)`.
645+
646+
## `is_optimizer`
647+
648+
If `is_optimizer = true`, the resulting struct is a of [`GenericOptimizer`](@ref),
649+
which is a subtype of [`MOI.AbstractOptimizer`](@ref), otherwise, it is a
650+
[`GenericModel`](@ref), which is a subtype of [`MOI.ModelLike`](@ref).
651+
652+
## VariableIndex
653+
654+
* The function [`MOI.VariableIndex`](@ref) must not be given in
655+
`scalar_functions`.
656+
* The model supports [`MOI.VariableIndex`](@ref)-in-`S` constraints where `S`
657+
is [`MOI.EqualTo`](@ref), [`MOI.GreaterThan`](@ref), [`MOI.LessThan`](@ref),
658+
[`MOI.Interval`](@ref), [`MOI.Integer`](@ref), [`MOI.ZeroOne`](@ref),
659+
[`MOI.Semicontinuous`](@ref) or [`MOI.Semiinteger`](@ref).
660+
* The sets supported with [`MOI.VariableIndex`](@ref) cannot be controlled from
661+
the macro; use [`UniversalFallback`](@ref) to support more sets.
662+
663+
## Examples
681664
682-
Let `MOI` denote `MathOptInterface`, `MOIU` denote `MOI.Utilities`.
683-
The macro would create the following types with
684-
[`struct_of_constraint_code`](@ref):
665+
The model describing a linear program would be:
685666
```julia
686-
struct LPModelScalarConstraints{T, C1, C2, C3, C4} <: MOIU.StructOfConstraints
687-
moi_equalto::C1
688-
moi_greaterthan::C2
689-
moi_lessthan::C3
690-
moi_interval::C4
691-
end
692-
struct LPModelVectorConstraints{T, C1, C2, C3} <: MOIU.StructOfConstraints
693-
moi_zeros::C1
694-
moi_nonnegatives::C2
695-
moi_nonpositives::C3
696-
end
697-
struct LPModelFunctionConstraints{T} <: MOIU.StructOfConstraints
698-
moi_scalaraffinefunction::LPModelScalarConstraints{
699-
T,
700-
MOIU.VectorOfConstraints{MOI.ScalarAffineFunction{T}, MOI.EqualTo{T}},
701-
MOIU.VectorOfConstraints{MOI.ScalarAffineFunction{T}, MOI.GreaterThan{T}},
702-
MOIU.VectorOfConstraints{MOI.ScalarAffineFunction{T}, MOI.LessThan{T}},
703-
MOIU.VectorOfConstraints{MOI.ScalarAffineFunction{T}, MOI.Interval{T}}
704-
}
705-
moi_vectorofvariables::LPModelVectorConstraints{
706-
T,
707-
MOIU.VectorOfConstraints{MOI.VectorOfVariables, MOI.Zeros},
708-
MOIU.VectorOfConstraints{MOI.VectorOfVariables, MOI.Nonnegatives},
709-
MOIU.VectorOfConstraints{MOI.VectorOfVariables, MOI.Nonpositives}
710-
}
711-
moi_vectoraffinefunction::LPModelVectorConstraints{
712-
T,
713-
MOIU.VectorOfConstraints{MOI.VectorAffineFunction{T}, MOI.Zeros},
714-
MOIU.VectorOfConstraints{MOI.VectorAffineFunction{T}, MOI.Nonnegatives},
715-
MOIU.VectorOfConstraints{MOI.VectorAffineFunction{T}, MOI.Nonpositives}
716-
}
717-
end
718-
const LPModel{T} = MOIU.GenericModel{T,MOIU.ObjectiveContainer{T},MOIU.VariablesContainer{T},LPModelFunctionConstraints{T}}
667+
@model(
668+
LPModel, # model_name
669+
(), # untyped scalar sets
670+
(MOI.EqualTo, MOI.GreaterThan, MOI.LessThan, MOI.Interval), # typed scalar sets
671+
(MOI.Zeros, MOI.Nonnegatives, MOI.Nonpositives), # untyped vector sets
672+
(), # typed vector sets
673+
(), # untyped scalar functions
674+
(MOI.ScalarAffineFunction,), # typed scalar functions
675+
(MOI.VectorOfVariables,), # untyped vector functions
676+
(MOI.VectorAffineFunction,), # typed vector functions
677+
false, # is_optimizer
678+
)
719679
```
720-
The type `LPModel` implements the MathOptInterface API except methods specific
721-
to optimizers like `optimize!` or `get` with `VariablePrimal`.
722680
"""
723681
macro model(
724682
model_name,
725-
ss,
726-
sst,
727-
vs,
728-
vst,
729-
sf,
730-
sft,
731-
vf,
732-
vft,
683+
scalar_sets,
684+
typed_scalar_sets,
685+
vector_sets,
686+
typed_vector_sets,
687+
scalar_functions,
688+
typed_scalar_functions,
689+
vector_functions,
690+
typed_vector_functions,
733691
is_optimizer = false,
734692
)
735-
scalar_sets = [SymbolSet.(ss.args, false); SymbolSet.(sst.args, true)]
736-
vector_sets = [SymbolSet.(vs.args, false); SymbolSet.(vst.args, true)]
737-
738-
scname = esc(Symbol(string(model_name) * "ScalarConstraints"))
739-
vcname = esc(Symbol(string(model_name) * "VectorConstraints"))
740-
741-
esc_model_name = esc(model_name)
742-
# TODO if there is only one function or one set, remove the layer
743-
744-
scalar_funs = [
745-
SymbolFun.(sf.args, false)
746-
SymbolFun.(sft.args, true)
747-
]
748-
vector_funs = [
749-
SymbolFun.(vf.args, false)
750-
SymbolFun.(vft.args, true)
751-
]
693+
scalar_sets = vcat(
694+
SymbolSet.(scalar_sets.args, false),
695+
SymbolSet.(typed_scalar_sets.args, true),
696+
)
697+
vector_sets = vcat(
698+
SymbolSet.(vector_sets.args, false),
699+
SymbolSet.(typed_vector_sets.args, true),
700+
)
701+
scalar_funs = vcat(
702+
SymbolFun.(scalar_functions.args, false),
703+
SymbolFun.(typed_scalar_functions.args, true),
704+
)
705+
vector_funs = vcat(
706+
SymbolFun.(vector_functions.args, false),
707+
SymbolFun.(typed_vector_functions.args, true),
708+
)
709+
scname = esc(Symbol("$(model_name)ScalarConstraints"))
710+
vcname = esc(Symbol("$(model_name)VectorConstraints"))
752711
funs = [scalar_funs; vector_funs]
753712
set_struct_types = map(eachindex(funs)) do i
754-
if i <= length(scalar_funs)
755-
cname = scname
756-
sets = scalar_sets
713+
cname, sets = if i <= length(scalar_funs)
714+
scname, scalar_sets
757715
else
758-
cname = vcname
759-
sets = vector_sets
716+
vcname, vector_sets
760717
end
761718
voc = map(sets) do set
762719
return :(VectorOfConstraints{$(_typed(funs[i])),$(_typed(set))})
763720
end
764721
return _struct_of_constraints_type(cname, voc, true)
765722
end
766-
func_name = esc(Symbol(string(model_name) * "FunctionConstraints"))
767-
func_typed = _struct_of_constraints_type(func_name, set_struct_types, false)
768-
T = esc(:T)
769-
generic = if is_optimizer
770-
:(GenericOptimizer{
771-
$T,
772-
ObjectiveContainer{$T},
773-
VariablesContainer{$T},
774-
$func_typed,
775-
})
776-
else
777-
:(GenericModel{
778-
$T,
779-
ObjectiveContainer{$T},
780-
VariablesContainer{$T},
781-
$func_typed,
782-
})
783-
end
784-
model_code = :(const $esc_model_name{$T} = $generic)
785-
expr = Expr(:block)
723+
func_name = esc(Symbol("$(model_name)FunctionConstraints"))
724+
expr = quote end
786725
if length(scalar_sets) >= 2
787726
push!(expr.args, struct_of_constraint_code(scname, scalar_sets))
788727
end
@@ -795,12 +734,26 @@ macro model(
795734
struct_of_constraint_code(func_name, funs, set_struct_types),
796735
)
797736
end
798-
push!(expr.args, model_code)
737+
func_typed = _struct_of_constraints_type(func_name, set_struct_types, false)
738+
T = esc(:T)
739+
generic = is_optimizer ? GenericOptimizer : GenericModel
740+
push!(
741+
expr.args,
742+
quote
743+
const $(esc(model_name)){$T} = $generic{
744+
$T,
745+
ObjectiveContainer{$T},
746+
VariablesContainer{$T},
747+
$func_typed,
748+
}
749+
end,
750+
)
799751
return expr
800752
end
801753

802754
const LessThanIndicatorOne{T} =
803755
MOI.Indicator{MOI.ACTIVATE_ON_ONE,MOI.LessThan{T}}
756+
804757
const LessThanIndicatorZero{T} =
805758
MOI.Indicator{MOI.ACTIVATE_ON_ZERO,MOI.LessThan{T}}
806759

0 commit comments

Comments
 (0)