153
153
154
154
function MOI. get (model:: AbstractModel , :: MOI.ListOfVariableAttributesSet )
155
155
ret = MOI. AbstractVariableAttribute[]
156
- if isempty (model. var_to_name)
156
+ if ! isempty (model. var_to_name)
157
157
push! (ret, MOI. VariableName ())
158
158
end
159
159
return ret
@@ -608,14 +608,12 @@ function _struct_of_constraints_type(name, subtypes, parametrized_type)
608
608
if length (subtypes) == 1
609
609
# Only one type, no need for a `StructOfConstraints`.
610
610
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
618
611
end
612
+ expr = Expr (:curly , name, esc (:T ))
613
+ if parametrized_type
614
+ append! (expr. args, subtypes)
615
+ end
616
+ return expr
619
617
end
620
618
621
619
# This macro is for expert/internal use only. Prefer the concrete Model type
@@ -634,155 +632,96 @@ end
634
632
is_optimizer = false
635
633
)
636
634
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
681
664
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:
685
666
```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
+ )
719
679
```
720
- The type `LPModel` implements the MathOptInterface API except methods specific
721
- to optimizers like `optimize!` or `get` with `VariablePrimal`.
722
680
"""
723
681
macro model (
724
682
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 ,
733
691
is_optimizer = false ,
734
692
)
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" ))
752
711
funs = [scalar_funs; vector_funs]
753
712
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
757
715
else
758
- cname = vcname
759
- sets = vector_sets
716
+ vcname, vector_sets
760
717
end
761
718
voc = map (sets) do set
762
719
return :(VectorOfConstraints{$ (_typed (funs[i])),$ (_typed (set))})
763
720
end
764
721
return _struct_of_constraints_type (cname, voc, true )
765
722
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
786
725
if length (scalar_sets) >= 2
787
726
push! (expr. args, struct_of_constraint_code (scname, scalar_sets))
788
727
end
@@ -795,12 +734,26 @@ macro model(
795
734
struct_of_constraint_code (func_name, funs, set_struct_types),
796
735
)
797
736
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
+ )
799
751
return expr
800
752
end
801
753
802
754
const LessThanIndicatorOne{T} =
803
755
MOI. Indicator{MOI. ACTIVATE_ON_ONE,MOI. LessThan{T}}
756
+
804
757
const LessThanIndicatorZero{T} =
805
758
MOI. Indicator{MOI. ACTIVATE_ON_ZERO,MOI. LessThan{T}}
806
759
0 commit comments